v2: range, *, function object
parent
4fc52948b3
commit
71653273f6
|
@ -378,7 +378,8 @@ pub fn (b []byte) hex() string {
|
|||
// TODO: implement for all types
|
||||
pub fn copy(dst, src []byte) int {
|
||||
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)
|
||||
return min
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
|
||||
pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral |
|
||||
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 |
|
||||
ForStmt | StructDecl | ForCStmt | ForInStmt
|
||||
|
@ -296,6 +296,13 @@ pub:
|
|||
ti table.Type
|
||||
}
|
||||
|
||||
// s[10..20]
|
||||
pub struct RangeExpr {
|
||||
pub:
|
||||
low Expr
|
||||
high Expr
|
||||
}
|
||||
|
||||
// string representaiton of expr
|
||||
pub fn (x Expr) str() string {
|
||||
match x {
|
||||
|
|
|
@ -194,112 +194,112 @@ fn (c &Checker) stmt(node ast.Stmt) {
|
|||
}
|
||||
ast.VarDecl {
|
||||
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 {
|
||||
// it.ti = typ
|
||||
println('VAR DECL UN!!!')
|
||||
// println('unresolved var')
|
||||
}
|
||||
}
|
||||
}
|
||||
ast.ForStmt {
|
||||
c.expr(it.cond)
|
||||
for stmt in it.stmts {
|
||||
c.stmt(stmt)
|
||||
ast.ForStmt {
|
||||
c.expr(it.cond)
|
||||
for stmt in it.stmts {
|
||||
c.stmt(stmt)
|
||||
}
|
||||
}
|
||||
}
|
||||
ast.ForCStmt {
|
||||
c.stmt(it.init)
|
||||
c.expr(it.cond)
|
||||
c.stmt(it.inc)
|
||||
for stmt in it.stmts {
|
||||
c.stmt(stmt)
|
||||
ast.ForCStmt {
|
||||
c.stmt(it.init)
|
||||
c.expr(it.cond)
|
||||
c.stmt(it.inc)
|
||||
for stmt in it.stmts {
|
||||
c.stmt(stmt)
|
||||
}
|
||||
}
|
||||
}
|
||||
// ast.StructDecl {}
|
||||
ast.ExprStmt {
|
||||
c.expr(it.expr)
|
||||
}
|
||||
else {}
|
||||
// ast.StructDecl {}
|
||||
ast.ExprStmt {
|
||||
c.expr(it.expr)
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (c &Checker) expr(node ast.Expr) table.Type {
|
||||
match node {
|
||||
ast.AssignExpr {
|
||||
c.check_assign_expr(it)
|
||||
}
|
||||
ast.IntegerLiteral {
|
||||
return table.int_type
|
||||
}
|
||||
// ast.FloatLiteral {}
|
||||
ast.PostfixExpr {
|
||||
return c.expr(it.expr)
|
||||
}
|
||||
/*
|
||||
pub fn (c &Checker) expr(node ast.Expr) table.Type {
|
||||
match node {
|
||||
ast.AssignExpr {
|
||||
c.check_assign_expr(it)
|
||||
}
|
||||
ast.IntegerLiteral {
|
||||
return table.int_type
|
||||
}
|
||||
// ast.FloatLiteral {}
|
||||
ast.PostfixExpr {
|
||||
return c.expr(it.expr)
|
||||
}
|
||||
/*
|
||||
ast.UnaryExpr {
|
||||
c.expr(it.left)
|
||||
}
|
||||
*/
|
||||
|
||||
ast.StringLiteral {
|
||||
return table.string_type
|
||||
}
|
||||
ast.PrefixExpr {
|
||||
return c.expr(it.right)
|
||||
}
|
||||
ast.InfixExpr {
|
||||
return c.infix_expr(it)
|
||||
}
|
||||
ast.StructInit {
|
||||
return c.check_struct_init(it)
|
||||
}
|
||||
ast.CallExpr {
|
||||
return c.call_expr(it)
|
||||
}
|
||||
ast.MethodCallExpr {
|
||||
return c.check_method_call_expr(it)
|
||||
}
|
||||
ast.ArrayInit {
|
||||
return c.array_init(it)
|
||||
}
|
||||
ast.Ident {
|
||||
if it.kind == .variable {
|
||||
info := it.info as ast.IdentVar
|
||||
if info.typ.kind != .unresolved {
|
||||
return info.typ
|
||||
ast.StringLiteral {
|
||||
return table.string_type
|
||||
}
|
||||
ast.PrefixExpr {
|
||||
return c.expr(it.right)
|
||||
}
|
||||
ast.InfixExpr {
|
||||
return c.infix_expr(it)
|
||||
}
|
||||
ast.StructInit {
|
||||
return c.check_struct_init(it)
|
||||
}
|
||||
ast.CallExpr {
|
||||
return c.call_expr(it)
|
||||
}
|
||||
ast.MethodCallExpr {
|
||||
return c.check_method_call_expr(it)
|
||||
}
|
||||
ast.ArrayInit {
|
||||
return c.array_init(it)
|
||||
}
|
||||
ast.Ident {
|
||||
if it.kind == .variable {
|
||||
info := it.info as ast.IdentVar
|
||||
if info.typ.kind != .unresolved {
|
||||
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 {
|
||||
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)
|
||||
// ast.BoolLiteral {}
|
||||
ast.SelectorExpr {
|
||||
return c.selector_expr(it)
|
||||
}
|
||||
if it.else_stmts.len > 0 {
|
||||
for stmt in it.else_stmts {
|
||||
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 {
|
||||
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) {
|
||||
print_backtrace()
|
||||
final_msg_line := '$c.file_name:$pos.line_nr: error: $s'
|
||||
eprintln(final_msg_line)
|
||||
/*
|
||||
pub fn (c &Checker) error(s string, pos token.Position) {
|
||||
print_backtrace()
|
||||
final_msg_line := '$c.file_name:$pos.line_nr: error: $s'
|
||||
eprintln(final_msg_line)
|
||||
/*
|
||||
if colored_output {
|
||||
eprintln(term.bold(term.red(final_msg_line)))
|
||||
}else{
|
||||
|
@ -307,5 +307,5 @@ pub fn (c &Checker) error(s string, pos token.Position) {
|
|||
}
|
||||
*/
|
||||
|
||||
exit(1)
|
||||
}
|
||||
exit(1)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
v.ast
|
||||
v.table
|
||||
v.checker
|
||||
// v.types
|
||||
term
|
||||
)
|
||||
|
||||
|
@ -25,7 +24,7 @@ pub fn cgen(files []ast.File, table &table.Table) string {
|
|||
definitions: strings.new_builder(100)
|
||||
table: table
|
||||
checker: checker.new_checker(table) // checker
|
||||
|
||||
|
||||
fn_decl: 0
|
||||
}
|
||||
for file in files {
|
||||
|
@ -267,10 +266,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
|||
g.write(it.field)
|
||||
}
|
||||
ast.IndexExpr {
|
||||
g.expr(it.left)
|
||||
g.write('[')
|
||||
g.expr(it.index)
|
||||
g.write(']')
|
||||
g.index_expr(it)
|
||||
}
|
||||
ast.IfExpr {
|
||||
// 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) {
|
||||
println(s)
|
||||
exit(1)
|
||||
|
|
|
@ -33,6 +33,7 @@ i < 10; i++;
|
|||
array_int nums = new_array_from_c_array(3, 3, sizeof(array_int), {
|
||||
1, 2, 3,
|
||||
});
|
||||
array_int nums2 = array_slice(nums, 0, 2);
|
||||
int number = nums[0];
|
||||
array_bool bools = new_array_from_c_array(2, 2, sizeof(array_bool), {
|
||||
true, false,
|
||||
|
|
|
@ -33,6 +33,7 @@ fn foo(a int) {
|
|||
|
||||
}
|
||||
nums := [1,2,3]
|
||||
nums2 := nums[..2]
|
||||
number := nums[0]
|
||||
bools := [true, false]
|
||||
b := bools[0]
|
||||
|
|
|
@ -231,6 +231,20 @@ pub fn (p mut Parser) assign_expr(left ast.Expr) ast.AssignExpr {
|
|||
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 {
|
||||
name := p.tok.lit
|
||||
|
@ -340,21 +354,26 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
|
|||
mut ident := ast.Ident{
|
||||
name: p.tok.lit
|
||||
}
|
||||
var := p.table.find_var(p.tok.lit) or {
|
||||
p.error('name expr unknown variable `$p.tok.lit`')
|
||||
exit(0)
|
||||
if var := p.table.find_var(p.tok.lit) {
|
||||
typ = var.typ
|
||||
ident.kind = .variable
|
||||
ident.info = ast.IdentVar{
|
||||
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()
|
||||
}
|
||||
typ = var.typ
|
||||
ident.kind = .variable
|
||||
ident.info = ast.IdentVar{
|
||||
typ: typ
|
||||
name: ident.name
|
||||
// expr: p.expr(0)// var.expr
|
||||
|
||||
}
|
||||
// ident.ti = ti
|
||||
node = ident
|
||||
p.next()
|
||||
}
|
||||
return node,typ
|
||||
}
|
||||
|
@ -372,7 +391,7 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
|
|||
node,typ = p.string_expr()
|
||||
}
|
||||
// -1, -a etc
|
||||
.minus, .amp {
|
||||
.minus, .amp, .mul {
|
||||
node,typ = p.prefix_expr()
|
||||
}
|
||||
// .amp {
|
||||
|
@ -412,21 +431,7 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
|
|||
node,typ = p.dot_expr(node, typ)
|
||||
}
|
||||
else if p.tok.kind == .lsbr {
|
||||
// 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..]
|
||||
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)
|
||||
node,typ = p.index_expr(node, typ)
|
||||
}
|
||||
else if p.tok.kind.is_infix() {
|
||||
node,typ = p.infix_expr(node)
|
||||
|
@ -459,23 +464,50 @@ fn (p mut Parser) prefix_expr() (ast.Expr,table.Type) {
|
|||
return expr,ti
|
||||
}
|
||||
|
||||
fn (p mut Parser) index_expr(left ast.Expr) ast.Expr {
|
||||
// ,table.Type) {
|
||||
fn (p mut Parser) index_expr(left ast.Expr, typ_ table.Type) (ast.Expr,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')
|
||||
p.next()
|
||||
println('start index expr')
|
||||
index,typ := p.expr(0)
|
||||
println('end expr typ=$typ.name')
|
||||
p.next() // [
|
||||
// `numbers[..end]`
|
||||
mut index_expr := ast.Expr{}
|
||||
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)
|
||||
println('got ]')
|
||||
// println('got ]')
|
||||
// /ti := table.int_type
|
||||
mut node := ast.Expr{}
|
||||
node = ast.IndexExpr{
|
||||
left: left
|
||||
index: index
|
||||
index: index_expr
|
||||
}
|
||||
return node
|
||||
// /return node,ti
|
||||
// return node
|
||||
return node,typ
|
||||
}
|
||||
|
||||
fn (p mut Parser) dot_expr(left ast.Expr, left_ti &table.Type) (ast.Expr,table.Type) {
|
||||
|
|
|
@ -357,6 +357,8 @@ const (
|
|||
)
|
||||
// precedence returns a tokens precedence if defined, otherwise lowest_prec
|
||||
pub fn (tok Token) precedence() int {
|
||||
// TODO
|
||||
// return int(precedences[int(tok)])
|
||||
match tok.kind {
|
||||
.lsbr {
|
||||
return 9
|
||||
|
|
Loading…
Reference in New Issue