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
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
}

View File

@ -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 {

View File

@ -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)
}

View File

@ -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)

View File

@ -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,

View File

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

View File

@ -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) {

View File

@ -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