v2: range, *, function object

pull/3632/head
Alexander Medvednikov 2020-02-02 14:31:54 +01:00
parent 4fc52948b3
commit 71653273f6
8 changed files with 201 additions and 136 deletions

View File

@ -378,7 +378,8 @@ pub fn (b []byte) hex() string {
// TODO: implement for all types // TODO: implement for all types
pub fn copy(dst, src []byte) int { pub fn copy(dst, src []byte) int {
if dst.len > 0 && src.len > 0 { if dst.len > 0 && src.len > 0 {
min := if dst.len < src.len { dst.len } else { src.len } mut min := 0
min = if dst.len < src.len { dst.len } else { src.len }
C.memcpy(dst.data, src[..min].data, dst.element_size * min) C.memcpy(dst.data, src[..min].data, dst.element_size * min)
return min return min
} }

View File

@ -10,7 +10,7 @@ import (
pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral |
FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr | FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr |
AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr
pub type Stmt = VarDecl | FnDecl | Return | Module | Import | ExprStmt | pub type Stmt = VarDecl | FnDecl | Return | Module | Import | ExprStmt |
ForStmt | StructDecl | ForCStmt | ForInStmt ForStmt | StructDecl | ForCStmt | ForInStmt
@ -296,6 +296,13 @@ pub:
ti table.Type ti table.Type
} }
// s[10..20]
pub struct RangeExpr {
pub:
low Expr
high Expr
}
// string representaiton of expr // string representaiton of expr
pub fn (x Expr) str() string { pub fn (x Expr) str() string {
match x { match x {

View File

@ -194,112 +194,112 @@ fn (c &Checker) stmt(node ast.Stmt) {
} }
ast.VarDecl { ast.VarDecl {
typ := c.expr(it.expr) typ := c.expr(it.expr)
println('1111var decl $typ.name it.typ=$it.typ.name $it.pos.line_nr') // println('var decl $typ.name it.typ=$it.typ.name $it.pos.line_nr')
if it.typ.kind == .unresolved { if it.typ.kind == .unresolved {
// it.ti = typ // it.ti = typ
println('VAR DECL UN!!!') // println('unresolved var')
}
} }
} ast.ForStmt {
ast.ForStmt { c.expr(it.cond)
c.expr(it.cond) for stmt in it.stmts {
for stmt in it.stmts { c.stmt(stmt)
c.stmt(stmt) }
} }
} ast.ForCStmt {
ast.ForCStmt { c.stmt(it.init)
c.stmt(it.init) c.expr(it.cond)
c.expr(it.cond) c.stmt(it.inc)
c.stmt(it.inc) for stmt in it.stmts {
for stmt in it.stmts { c.stmt(stmt)
c.stmt(stmt) }
} }
} // ast.StructDecl {}
// ast.StructDecl {} ast.ExprStmt {
ast.ExprStmt { c.expr(it.expr)
c.expr(it.expr) }
} else {}
else {} }
} }
}
pub fn (c &Checker) expr(node ast.Expr) table.Type { pub fn (c &Checker) expr(node ast.Expr) table.Type {
match node { match node {
ast.AssignExpr { ast.AssignExpr {
c.check_assign_expr(it) c.check_assign_expr(it)
} }
ast.IntegerLiteral { ast.IntegerLiteral {
return table.int_type return table.int_type
} }
// ast.FloatLiteral {} // ast.FloatLiteral {}
ast.PostfixExpr { ast.PostfixExpr {
return c.expr(it.expr) return c.expr(it.expr)
} }
/* /*
ast.UnaryExpr { ast.UnaryExpr {
c.expr(it.left) c.expr(it.left)
} }
*/ */
ast.StringLiteral { ast.StringLiteral {
return table.string_type return table.string_type
} }
ast.PrefixExpr { ast.PrefixExpr {
return c.expr(it.right) return c.expr(it.right)
} }
ast.InfixExpr { ast.InfixExpr {
return c.infix_expr(it) return c.infix_expr(it)
} }
ast.StructInit { ast.StructInit {
return c.check_struct_init(it) return c.check_struct_init(it)
} }
ast.CallExpr { ast.CallExpr {
return c.call_expr(it) return c.call_expr(it)
} }
ast.MethodCallExpr { ast.MethodCallExpr {
return c.check_method_call_expr(it) return c.check_method_call_expr(it)
} }
ast.ArrayInit { ast.ArrayInit {
return c.array_init(it) return c.array_init(it)
} }
ast.Ident { ast.Ident {
if it.kind == .variable { if it.kind == .variable {
info := it.info as ast.IdentVar info := it.info as ast.IdentVar
if info.typ.kind != .unresolved { if info.typ.kind != .unresolved {
return info.typ return info.typ
}
return c.expr(info.expr)
} }
return c.expr(info.expr) return table.void_type
} }
return table.void_type // ast.BoolLiteral {}
} ast.SelectorExpr {
// ast.BoolLiteral {} return c.selector_expr(it)
ast.SelectorExpr {
return c.selector_expr(it)
}
ast.IndexExpr {
c.expr(it.left)
c.expr(it.index)
}
ast.IfExpr {
c.expr(it.cond)
for i, stmt in it.stmts {
c.stmt(stmt)
} }
if it.else_stmts.len > 0 { ast.IndexExpr {
for stmt in it.else_stmts { c.expr(it.left)
c.expr(it.index)
}
ast.IfExpr {
c.expr(it.cond)
for i, stmt in it.stmts {
c.stmt(stmt) c.stmt(stmt)
} }
if it.else_stmts.len > 0 {
for stmt in it.else_stmts {
c.stmt(stmt)
}
}
} }
} else {}
else {} }
return table.void_type
} }
return table.void_type
}
pub fn (c &Checker) error(s string, pos token.Position) { pub fn (c &Checker) error(s string, pos token.Position) {
print_backtrace() print_backtrace()
final_msg_line := '$c.file_name:$pos.line_nr: error: $s' final_msg_line := '$c.file_name:$pos.line_nr: error: $s'
eprintln(final_msg_line) eprintln(final_msg_line)
/* /*
if colored_output { if colored_output {
eprintln(term.bold(term.red(final_msg_line))) eprintln(term.bold(term.red(final_msg_line)))
}else{ }else{
@ -307,5 +307,5 @@ pub fn (c &Checker) error(s string, pos token.Position) {
} }
*/ */
exit(1) exit(1)
} }

View File

@ -5,7 +5,6 @@ import (
v.ast v.ast
v.table v.table
v.checker v.checker
// v.types
term term
) )
@ -267,10 +266,7 @@ fn (g mut Gen) expr(node ast.Expr) {
g.write(it.field) g.write(it.field)
} }
ast.IndexExpr { ast.IndexExpr {
g.expr(it.left) g.index_expr(it)
g.write('[')
g.expr(it.index)
g.write(']')
} }
ast.IfExpr { ast.IfExpr {
// If expression? Assign the value to a temp var. // If expression? Assign the value to a temp var.
@ -307,6 +303,31 @@ fn (g mut Gen) expr(node ast.Expr) {
} }
} }
fn (g mut Gen) index_expr(node ast.IndexExpr) {
// TODO else doesn't work with sum types
mut is_range := false
match node.index {
ast.RangeExpr {
is_range = true
g.write('array_slice(')
g.expr(node.left)
g.write(', ')
// g.expr(it.low)
g.write('0')
g.write(', ')
g.expr(it.high)
g.write(')')
}
else {}
}
if !is_range {
g.expr(node.left)
g.write('[')
g.expr(node.index)
g.write(']')
}
}
fn verror(s string) { fn verror(s string) {
println(s) println(s)
exit(1) exit(1)

View File

@ -33,6 +33,7 @@ i < 10; i++;
array_int nums = new_array_from_c_array(3, 3, sizeof(array_int), { array_int nums = new_array_from_c_array(3, 3, sizeof(array_int), {
1, 2, 3, 1, 2, 3,
}); });
array_int nums2 = array_slice(nums, 0, 2);
int number = nums[0]; int number = nums[0];
array_bool bools = new_array_from_c_array(2, 2, sizeof(array_bool), { array_bool bools = new_array_from_c_array(2, 2, sizeof(array_bool), {
true, false, true, false,

View File

@ -33,6 +33,7 @@ fn foo(a int) {
} }
nums := [1,2,3] nums := [1,2,3]
nums2 := nums[..2]
number := nums[0] number := nums[0]
bools := [true, false] bools := [true, false]
b := bools[0] b := bools[0]

View File

@ -231,6 +231,20 @@ pub fn (p mut Parser) assign_expr(left ast.Expr) ast.AssignExpr {
return node return node
} }
fn (p mut Parser) range_expr(low ast.Expr) ast.Expr {
// ,table.Type) {
p.next()
high,typ := p.expr(0)
if typ.kind != .int {
p.error('non-integer index `$typ.name`')
}
node := ast.RangeExpr{
low: low
high: high
}
return node
}
/* /*
pub fn (p mut Parser) assign_stmt() ast.AssignStmt { pub fn (p mut Parser) assign_stmt() ast.AssignStmt {
name := p.tok.lit name := p.tok.lit
@ -340,21 +354,26 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
mut ident := ast.Ident{ mut ident := ast.Ident{
name: p.tok.lit name: p.tok.lit
} }
var := p.table.find_var(p.tok.lit) or { if var := p.table.find_var(p.tok.lit) {
p.error('name expr unknown variable `$p.tok.lit`') typ = var.typ
exit(0) ident.kind = .variable
} ident.info = ast.IdentVar{
typ = var.typ typ: typ
ident.kind = .variable name: ident.name
ident.info = ast.IdentVar{ // expr: p.expr(0)// var.expr
typ: typ
name: ident.name
// expr: p.expr(0)// var.expr
}
// ident.ti = ti
node = ident
p.next()
}else{
// Function object (not a call), e.g. `onclick(my_click)`
p.table.find_fn(p.tok.lit) or {
p.error('name expr unknown variable `$p.tok.lit`')
exit(0)
}
p.next()
} }
// ident.ti = ti
node = ident
p.next()
} }
return node,typ return node,typ
} }
@ -372,7 +391,7 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
node,typ = p.string_expr() node,typ = p.string_expr()
} }
// -1, -a etc // -1, -a etc
.minus, .amp { .minus, .amp, .mul {
node,typ = p.prefix_expr() node,typ = p.prefix_expr()
} }
// .amp { // .amp {
@ -412,21 +431,7 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
node,typ = p.dot_expr(node, typ) node,typ = p.dot_expr(node, typ)
} }
else if p.tok.kind == .lsbr { else if p.tok.kind == .lsbr {
// TODO node,typ = p.index_expr(node, typ)
// info := ti.info as table.Array
// ti = p.table.types[info.elem_type_idx]
if typ.name.starts_with('array_') {
elm_typ := typ.name[6..]
x := p.table.find_type(elm_typ) or {
p.error(elm_typ)
exit(0)
}
typ = x
}
else {
typ = table.int_type
}
node = p.index_expr(node)
} }
else if p.tok.kind.is_infix() { else if p.tok.kind.is_infix() {
node,typ = p.infix_expr(node) node,typ = p.infix_expr(node)
@ -459,23 +464,50 @@ fn (p mut Parser) prefix_expr() (ast.Expr,table.Type) {
return expr,ti return expr,ti
} }
fn (p mut Parser) index_expr(left ast.Expr) ast.Expr { fn (p mut Parser) index_expr(left ast.Expr, typ_ table.Type) (ast.Expr,table.Type) {
// ,table.Type) { mut typ := typ_
// TODO
// info := ti.info as table.Array
// ti = p.table.types[info.elem_type_idx]
if typ.name.starts_with('array_') {
elm_typ := typ.name[6..]
// TODO `typ = ... or ...`
x := p.table.find_type(elm_typ) or {
p.error(elm_typ)
exit(0)
}
typ = x
}
else {
typ = table.int_type
}
// println('index expr$p.tok.str() line=$p.tok.line_nr') // println('index expr$p.tok.str() line=$p.tok.line_nr')
p.next() p.next() // [
println('start index expr') // `numbers[..end]`
index,typ := p.expr(0) mut index_expr := ast.Expr{}
println('end expr typ=$typ.name') if p.tok.kind == .dotdot {
index_expr = p.range_expr(left)
typ = typ_ // set the type back to array
}
else {
// println('start index expr')
mut index_type := table.Type{}
index_expr,index_type = p.expr(0)
if index_type.kind != .int {
p.error('non-integer index (type `$typ.name`)')
}
}
// println('end expr typ=$typ.name')
p.check(.rsbr) p.check(.rsbr)
println('got ]') // println('got ]')
// /ti := table.int_type // /ti := table.int_type
mut node := ast.Expr{} mut node := ast.Expr{}
node = ast.IndexExpr{ node = ast.IndexExpr{
left: left left: left
index: index index: index_expr
} }
return node // return node
// /return node,ti return node,typ
} }
fn (p mut Parser) dot_expr(left ast.Expr, left_ti &table.Type) (ast.Expr,table.Type) { fn (p mut Parser) dot_expr(left ast.Expr, left_ti &table.Type) (ast.Expr,table.Type) {

View File

@ -357,6 +357,8 @@ const (
) )
// precedence returns a tokens precedence if defined, otherwise lowest_prec // precedence returns a tokens precedence if defined, otherwise lowest_prec
pub fn (tok Token) precedence() int { pub fn (tok Token) precedence() int {
// TODO
// return int(precedences[int(tok)])
match tok.kind { match tok.kind {
.lsbr { .lsbr {
return 9 return 9