From 9f4661391df93a345e46de831023c8c77abb01e0 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 22 Jan 2020 21:34:38 +0100 Subject: [PATCH] v2: simplify the type system; an initial version of the V interpreter --- vlib/builtin/array_test.v | 2 +- vlib/builtin/map.v | 2 +- vlib/compiler/cc.v | 16 +- vlib/compiler/expression.v | 5 +- vlib/compiler/main.v | 1 - vlib/eventbus/eventbus_test.v | 2 +- vlib/fontstash/fontstash_funcs.v | 2 +- vlib/fontstash/fontstash_structs.v | 2 +- vlib/os/const_nix.v | 2 +- vlib/sokol/gfx/enums.v | 2 +- vlib/sokol/gfx/gfx_funcs.v | 2 +- vlib/sokol/gfx/gfx_structs.v | 2 +- vlib/sokol/gfx/gfx_utils.v | 2 +- vlib/sokol/sapp/enums.v | 2 +- vlib/sokol/sfons/sfons_funcs.v | 2 +- vlib/sokol/sgl/sgl_funcs.v | 2 +- vlib/sokol/sgl/sgl_structs.v | 2 +- vlib/v/ast/ast.v | 91 +++++---- vlib/v/checker/checker.v | 141 ++++++++----- vlib/v/eval/eval.v | 104 ++++++++++ vlib/v/gen/cgen.v | 29 ++- vlib/v/gen/jsgen.v | 15 +- vlib/v/gen/tests/1.c | 39 +++- vlib/v/gen/tests/1.vv | 21 +- vlib/v/gen/x64/gen.v | 5 +- vlib/v/parser/fn.v | 36 ++-- vlib/v/parser/{a_type.v => parse_type.v} | 64 +++--- vlib/v/parser/parser.v | 243 +++++++++++++---------- vlib/v/parser/parser_test.v | 51 ++++- vlib/v/{types/types.v => table/atypes.v} | 234 ++++++++++++++++------ vlib/v/table/table.v | 233 ++++++++-------------- vlib/v/token/position.v | 3 +- vlib/v/types/types_test.v | 5 - 33 files changed, 847 insertions(+), 517 deletions(-) create mode 100644 vlib/v/eval/eval.v rename vlib/v/parser/{a_type.v => parse_type.v} (54%) rename vlib/v/{types/types.v => table/atypes.v} (50%) delete mode 100644 vlib/v/types/types_test.v diff --git a/vlib/builtin/array_test.v b/vlib/builtin/array_test.v index 48918f1cc0..01e0dadf17 100644 --- a/vlib/builtin/array_test.v +++ b/vlib/builtin/array_test.v @@ -589,4 +589,4 @@ fn test_clear() { arr.clear() assert arr.len == 0 -} \ No newline at end of file +} diff --git a/vlib/builtin/map.v b/vlib/builtin/map.v index 0199ca5919..ee12a2d991 100644 --- a/vlib/builtin/map.v +++ b/vlib/builtin/map.v @@ -441,4 +441,4 @@ pub fn (m map_string) str() string { } sb.writeln('}') return sb.str() -} \ No newline at end of file +} diff --git a/vlib/compiler/cc.v b/vlib/compiler/cc.v index 94ab5d883a..afb33ccdd9 100644 --- a/vlib/compiler/cc.v +++ b/vlib/compiler/cc.v @@ -134,13 +134,13 @@ fn (v mut V) cc() { } if !v.pref.is_so - && v.pref.build_mode != .build_module + && v.pref.build_mode != .build_module && os.user_os() == 'windows' && !v.out_name.ends_with('.exe') { v.out_name += '.exe' } - + // linux_host := os.user_os() == 'linux' v.log('cc() isprod=$v.pref.is_prod outname=$v.out_name') if v.pref.is_so { @@ -356,13 +356,11 @@ start: if res.output.len < 30 { println(res.output) } else { - max := 50 - n := if res.output.len > max { max } else { res.output.len } - partial_output := res.output[res.output.len-n..].trim_right('\r\n') - print(partial_output) - if n < max { - println('...\n(Use `v -cg` to print the entire error message)\n') - } + q := res.output.all_after('error: ').limit(150) + println('==================') + println(q) + println('==================') + println('...\n(Use `v -cg` to print the entire error message)\n') } } verror('C error. This should never happen. ' + '\nPlease create a GitHub issue: https://github.com/vlang/v/issues/new/choose') diff --git a/vlib/compiler/expression.v b/vlib/compiler/expression.v index bdf423678d..c32c4d1f6e 100644 --- a/vlib/compiler/expression.v +++ b/vlib/compiler/expression.v @@ -63,7 +63,7 @@ fn (p mut Parser) bool_expression() string { p.gen('}') //p.satisfies_interface(expected, typ, true) } - // e.g. `return BinaryExpr{}` in a function expecting `Expr` + // e.g. `return InfixExpr{}` in a function expecting `Expr` if expected != typ && expected in p.table.sum_types { // TODO perf //p.warn('SUM CAST exp=$expected typ=$typ p.exp=$p.expected_type') T := p.table.find_type(typ) @@ -87,7 +87,8 @@ fn (p mut Parser) bool_expression() string { if typ in p.table.sum_types { T := p.table.find_type(cast_typ) if T.parent != typ { - p.error('cannot cast `$typ` to `$cast_typ`. `$cast_typ` is not a variant of `$typ`') + p.error('cannot cast `$typ` to `$cast_typ`. `$cast_typ` is not a variant of `$typ`' + + 'parent=$T.parent') } p.cgen.set_placeholder(start_ph, '*($cast_typ*)') p.gen('.obj') diff --git a/vlib/compiler/main.v b/vlib/compiler/main.v index ccfec1033c..62c0db8e1b 100644 --- a/vlib/compiler/main.v +++ b/vlib/compiler/main.v @@ -405,7 +405,6 @@ pub fn (v mut V) compile_x64() { } //v.files << v.v_files_from_dir(filepath.join(v.pref.vlib_path,'builtin','bare')) v.files << v.dir - mut b := builder.new_builder() b.build_x64(v.files, v.out_name) } diff --git a/vlib/eventbus/eventbus_test.v b/vlib/eventbus/eventbus_test.v index 173188459c..976791af45 100644 --- a/vlib/eventbus/eventbus_test.v +++ b/vlib/eventbus/eventbus_test.v @@ -32,4 +32,4 @@ fn test_eventbus(){ fn on_test(sender voidptr, ev &EventData) { assert ev.data == "hello" -} \ No newline at end of file +} diff --git a/vlib/fontstash/fontstash_funcs.v b/vlib/fontstash/fontstash_funcs.v index e2977affdf..f3e97a8d58 100644 --- a/vlib/fontstash/fontstash_funcs.v +++ b/vlib/fontstash/fontstash_funcs.v @@ -47,4 +47,4 @@ fn C.fonsGetTextureData(s &C.FONScontext, width &int, height &int) byteptr fn C.fonsValidateTexture(s &C.FONScontext, dirty &int) int // Draws the stash texture for debugging -fn C.fonsDrawDebug(s &C.FONScontext, x f32, y f32) \ No newline at end of file +fn C.fonsDrawDebug(s &C.FONScontext, x f32, y f32) diff --git a/vlib/fontstash/fontstash_structs.v b/vlib/fontstash/fontstash_structs.v index 5989df29e9..b851e5eec0 100644 --- a/vlib/fontstash/fontstash_structs.v +++ b/vlib/fontstash/fontstash_structs.v @@ -77,4 +77,4 @@ pub struct C.FONStextIter { pub struct C.FONSfont {} -pub struct C.FONScontext {} \ No newline at end of file +pub struct C.FONScontext {} diff --git a/vlib/os/const_nix.v b/vlib/os/const_nix.v index adc63078bf..1069193a28 100644 --- a/vlib/os/const_nix.v +++ b/vlib/os/const_nix.v @@ -12,4 +12,4 @@ const ( O_APPEND = 000002000 // append data to the file when writing. O_NONBLOCK = 000004000 // prevents blocking when opening files O_SYNC = 000010000 // open for synchronous I/O. -) \ No newline at end of file +) diff --git a/vlib/sokol/gfx/enums.v b/vlib/sokol/gfx/enums.v index d1c2f613e1..5fea066fdb 100644 --- a/vlib/sokol/gfx/enums.v +++ b/vlib/sokol/gfx/enums.v @@ -301,4 +301,4 @@ pub enum Action { load dontcare _num -} \ No newline at end of file +} diff --git a/vlib/sokol/gfx/gfx_funcs.v b/vlib/sokol/gfx/gfx_funcs.v index 383b9c677f..25459ef700 100644 --- a/vlib/sokol/gfx/gfx_funcs.v +++ b/vlib/sokol/gfx/gfx_funcs.v @@ -53,4 +53,4 @@ fn C.sg_query_buffer_defaults(desc &C.sg_buffer) C.sg_buffer_desc fn C.sg_query_image_defaults(desc &C.sg_image) C.sg_image_desc fn C.sg_query_shader_defaults(desc &C.sg_shader) C.sg_shader_desc fn C.sg_query_pipeline_defaults(desc &C.sg_pipeline) C.sg_pipeline_desc -fn C.sg_query_pass_defaults(desc &C.sg_pass) C.sg_pass_desc \ No newline at end of file +fn C.sg_query_pass_defaults(desc &C.sg_pass) C.sg_pass_desc diff --git a/vlib/sokol/gfx/gfx_structs.v b/vlib/sokol/gfx/gfx_structs.v index 2212b678fa..ad061cf1ce 100644 --- a/vlib/sokol/gfx/gfx_structs.v +++ b/vlib/sokol/gfx/gfx_structs.v @@ -457,4 +457,4 @@ pub mut: // layer int // slice int // } -} \ No newline at end of file +} diff --git a/vlib/sokol/gfx/gfx_utils.v b/vlib/sokol/gfx/gfx_utils.v index 50a5fc02bc..7fa071bbd2 100644 --- a/vlib/sokol/gfx/gfx_utils.v +++ b/vlib/sokol/gfx/gfx_utils.v @@ -9,4 +9,4 @@ pub fn create_clear_pass(r, g, b, a f32) C.sg_pass_action { mut pass_action := sg_pass_action{} pass_action.colors[0] = color_action return pass_action -} \ No newline at end of file +} diff --git a/vlib/sokol/sapp/enums.v b/vlib/sokol/sapp/enums.v index 8552b6effe..8644b67f51 100644 --- a/vlib/sokol/sapp/enums.v +++ b/vlib/sokol/sapp/enums.v @@ -155,4 +155,4 @@ pub enum KeyCode { right_alt = 346 right_super = 347 menu = 348 -} \ No newline at end of file +} diff --git a/vlib/sokol/sfons/sfons_funcs.v b/vlib/sokol/sfons/sfons_funcs.v index 93152439d6..ea49749a22 100644 --- a/vlib/sokol/sfons/sfons_funcs.v +++ b/vlib/sokol/sfons/sfons_funcs.v @@ -3,4 +3,4 @@ module sfons fn C.sfons_create(width int, height int, flags int) &C.FONScontext fn C.sfons_destroy(ctx &FONScontext) fn C.sfons_rgba(r byte, g byte, b byte, a byte) u32 -fn C.sfons_flush(ctx &FONScontext) \ No newline at end of file +fn C.sfons_flush(ctx &FONScontext) diff --git a/vlib/sokol/sgl/sgl_funcs.v b/vlib/sokol/sgl/sgl_funcs.v index 8afaea5812..143aa2e795 100644 --- a/vlib/sokol/sgl/sgl_funcs.v +++ b/vlib/sokol/sgl/sgl_funcs.v @@ -86,4 +86,4 @@ fn C.sgl_v3f_t2f_c1i(x f32, y f32, z f32, u f32, v f32, rgba u32) fn C.sgl_end() /* render everything */ -fn C.sgl_draw() \ No newline at end of file +fn C.sgl_draw() diff --git a/vlib/sokol/sgl/sgl_structs.v b/vlib/sokol/sgl/sgl_structs.v index 5d7f06ed2d..d7256e5943 100644 --- a/vlib/sokol/sgl/sgl_structs.v +++ b/vlib/sokol/sgl/sgl_structs.v @@ -21,4 +21,4 @@ pub struct C.sgl_desc_t { depth_format C.sg_pixel_format sample_count int face_winding C.sg_face_winding /* default front face winding is CCW */ -} \ No newline at end of file +} diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 94ddadf17d..354275ba20 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -5,11 +5,12 @@ module ast import ( v.token - v.types + v.table ) -pub type Expr = BinaryExpr | UnaryExpr | IfExpr | StringLiteral | IntegerLiteral | -FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr | AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr +pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | +FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr | +AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr pub type Stmt = VarDecl | FnDecl | Return | Module | Import | ExprStmt | ForStmt | StructDecl | ForCStmt | ForInStmt @@ -18,7 +19,7 @@ ForStmt | StructDecl | ForCStmt | ForInStmt pub struct ExprStmt { pub: expr Expr - ti types.TypeIdent + ti table.Type } pub struct IntegerLiteral { @@ -62,7 +63,7 @@ pub struct Field { pub: name string // type_idx int - ti types.TypeIdent + ti table.Type } pub struct StructDecl { @@ -76,7 +77,7 @@ pub: pub struct StructInit { pub: pos token.Position - ti types.TypeIdent + ti table.Type fields []string exprs []Expr } @@ -92,7 +93,7 @@ pub: pub struct Arg { pub: - ti types.TypeIdent + ti table.Type name string } @@ -100,7 +101,7 @@ pub struct FnDecl { pub: name string stmts []Stmt - ti types.TypeIdent + ti table.Type args []Arg is_pub bool receiver Field @@ -108,33 +109,33 @@ pub: pub struct CallExpr { pub: - // tok token.Token - pos token.Position +// tok token.Token + pos token.Position mut: - // func Expr - name string - args []Expr +// func Expr + name string + args []Expr } pub struct MethodCallExpr { pub: - // tok token.Token - pos token.Position - expr Expr - name string - args []Expr +// tok token.Token + pos token.Position + expr Expr + name string + args []Expr } pub struct Return { pub: - pos token.Position - expected_ti types.TypeIdent // TODO: remove once checker updated - exprs []Expr + pos token.Position + expected_ti table.Type // TODO: remove once checker updated + exprs []Expr } /* pub enum Expr { - Binary(BinaryExpr) + Binary(InfixExpr) If(IfExpr) Integer(IntegerExpr) } @@ -150,12 +151,12 @@ pub struct Stmt { pub struct VarDecl { pub: - name string - expr Expr + name string + expr Expr is_mut bool - mut: - ti types.TypeIdent - pos token.Position +mut: + typ table.Type + pos token.Position } pub struct File { @@ -168,7 +169,8 @@ pub: pub struct IdentVar { pub: expr Expr - ti types.TypeIdent + typ table.Type + name string } type IdentInfo = IdentVar @@ -190,17 +192,19 @@ mut: info IdentInfo } -pub struct BinaryExpr { +pub struct InfixExpr { pub: // op BinaryOp - op token.Kind - pos token.Position - left Expr - // left_ti types.TypeIdent - right Expr - // right_ti types.TypeIdent + op token.Kind + pos token.Position + left Expr + left_type table.Type + right Expr + right_type table.Type } +/* +// renamed to PrefixExpr pub struct UnaryExpr { pub: // tok_kind token.Kind @@ -208,6 +212,8 @@ pub: op token.Kind left Expr } +*/ + pub struct PostfixExpr { pub: @@ -225,7 +231,7 @@ pub struct IndexExpr { pub: // op token.Kind left Expr - index Expr + index Expr // [0], [start..end] etc } pub struct IfExpr { @@ -234,7 +240,7 @@ pub: cond Expr stmts []Stmt else_stmts []Stmt - ti types.TypeIdent + ti table.Type left Expr // `a` in `a := if ...` } @@ -261,7 +267,7 @@ pub: pub struct ReturnStmt { tok_kind token.Kind // or pos - pos token.Position + pos token.Position results []Expr } @@ -287,18 +293,21 @@ pub struct ArrayInit { pub: pos token.Position exprs []Expr - ti types.TypeIdent + ti table.Type } // string representaiton of expr pub fn (x Expr) str() string { match x { - BinaryExpr { + InfixExpr { return '(${it.left.str()} $it.op.str() ${it.right.str()})' } - UnaryExpr { + /* + PrefixExpr { return it.left.str() + it.op.str() } + */ + IntegerLiteral { return it.val.str() } diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index b12f08492a..7729be21fa 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -6,14 +6,13 @@ module checker import ( v.ast v.table - v.types v.token ) pub struct Checker { - table &table.Table + table &table.Table mut: - file_name string + file_name string // TODO: resolved } @@ -36,7 +35,7 @@ pub fn (c mut Checker) check_files(v_files []string, ast_files []ast.File) { } } -pub fn (c &Checker) check_struct_init(struct_init ast.StructInit) { +pub fn (c &Checker) check_struct_init(struct_init ast.StructInit) table.Type { typ := c.table.find_type(struct_init.ti.name) or { c.error('unknown struct: $struct_init.ti.name', struct_init.pos) panic('') @@ -46,100 +45,116 @@ pub fn (c &Checker) check_struct_init(struct_init ast.StructInit) { c.error('unknown struct: $struct_init.ti.name', struct_init.pos) } .struct_ { - info := typ.info as types.Struct + info := typ.info as table.Struct for i, expr in struct_init.exprs { field := info.fields[i] - expr_ti := c.table.get_expr_ti(expr) - if !c.table.check(expr_ti, field.ti) { - c.error('cannot assign $expr_ti.name as $field.ti.name for field $field.name', struct_init.pos) + // expr_ti := c.expr(expr) + field_type := c.expr(expr) + if !c.table.check(field_type, field.ti) { + c.error('cannot assign $field_type.name as $field.ti.name for field $field.name', struct_init.pos) } } } else {} } + return struct_init.ti } -pub fn (c &Checker) check_binary_expr(binary_expr ast.BinaryExpr) { - left_ti := c.table.get_expr_ti(binary_expr.left) - right_ti := c.table.get_expr_ti(binary_expr.right) +pub fn (c &Checker) infix_expr(infix_expr ast.InfixExpr) table.Type { + left_ti := c.expr(infix_expr.left) + right_ti := c.expr(infix_expr.right) if !c.table.check(&right_ti, &left_ti) { - c.error('binary expr: cannot use $right_ti.name as $left_ti.name', binary_expr.pos) + // if !c.table.check(&infix_expr.right_type, &infix_expr.right_type) { + // c.error('infix expr: cannot use `$infix_expr.right_type.name` as `$infix_expr.left_type.name`', infix_expr.pos) + c.error('infix expr: cannot use `$left_ti.name` as `$right_ti.name`', infix_expr.pos) } + return left_ti } fn (c &Checker) check_assign_expr(assign_expr ast.AssignExpr) { - left_ti := c.table.get_expr_ti(assign_expr.left) - right_ti := c.table.get_expr_ti(assign_expr.val) + left_ti := c.expr(assign_expr.left) + right_ti := c.expr(assign_expr.val) if !c.table.check(right_ti, left_ti) { c.error('cannot assign $right_ti.name to $left_ti.name', assign_expr.pos) } } -pub fn (c &Checker) check_call_expr(call_expr ast.CallExpr) { +pub fn (c &Checker) call_expr(call_expr ast.CallExpr) table.Type { fn_name := call_expr.name if f := c.table.find_fn(fn_name) { // return_ti := f.return_ti if call_expr.args.len < f.args.len { c.error('too few arguments in call to `$fn_name`', call_expr.pos) - } else if call_expr.args.len > f.args.len { + } + else if call_expr.args.len > f.args.len { c.error('too many arguments in call to `$fn_name`', call_expr.pos) } for i, arg in f.args { arg_expr := call_expr.args[i] - ti := c.table.get_expr_ti(arg_expr) - if !c.table.check(&ti, &arg.ti) { - c.error('cannot use type `$ti.name` as type `$arg.ti.name` in argument to `$fn_name`', call_expr.pos) + ti := c.expr(arg_expr) + if !c.table.check(&ti, &arg.typ) { + c.error('!cannot use type `$ti.name` as type `$arg.typ.name` in argument to `$fn_name`', call_expr.pos) } } - } else { + return f.return_type + }else{ c.error('unknown fn: $fn_name', call_expr.pos) + exit(0) // c.warn('unknown function `$fn_name`') } } -pub fn (c &Checker) check_method_call_expr(method_call_expr ast.MethodCallExpr) { - ti := c.table.get_expr_ti(method_call_expr.expr) +pub fn (c &Checker) check_method_call_expr(method_call_expr ast.MethodCallExpr) table.Type { + ti := c.expr(method_call_expr.expr) if !c.table.has_method(ti.idx, method_call_expr.name) { c.error('type `$ti.name` has no method `$method_call_expr.name`', method_call_expr.pos) } + return ti } -pub fn (c &Checker) check_selector_expr(selector_expr ast.SelectorExpr) { - ti := c.table.get_expr_ti(selector_expr.expr) +pub fn (c &Checker) selector_expr(selector_expr ast.SelectorExpr) table.Type { + ti := c.expr(selector_expr.expr) field_name := selector_expr.field - // struct_ := c.table.types[ti.idx] as types.Struct + struct_ := c.table.types[ti.idx] + // struct_info := struct_.info as table.Struct typ := c.table.types[ti.idx] match typ.kind { .struct_ { // if !c.table.struct_has_field(it, field) { - // c.error('AAA unknown field `${it.name}.$field`') + // c.error('AAA unknown field `${it.name}.$field`') // } // TODO: fix bug - c.table.struct_find_field(typ, field_name) or { + field := c.table.struct_find_field(typ, field_name) or { c.error('unknown field `${typ.name}.$field_name`', selector_expr.pos) + exit(0) } + return field.ti } else { c.error('$ti.name is not a struct', selector_expr.pos) } } + return table.void_type } // TODO: non deferred -pub fn (c &Checker) check_return_stmt(return_stmt ast.Return) { - mut got_tis := []types.TypeIdent +pub fn (c &Checker) return_stmt(return_stmt ast.Return) { + mut got_tis := []table.Type + if return_stmt.exprs.len == 0 { + return + } for expr in return_stmt.exprs { - ti := c.table.get_expr_ti(expr) + ti := c.expr(expr) got_tis << ti } expected_ti := return_stmt.expected_ti mut expected_tis := [expected_ti] if expected_ti.kind == .multi_return { mr_type := c.table.types[expected_ti.idx] - mr_info := mr_type.info as types.MultiReturn + mr_info := mr_type.info as table.MultiReturn expected_tis = mr_info.tis } - if expected_tis.len != got_tis.len { + if expected_tis.len > 0 && expected_tis.len != got_tis.len { c.error('wrong number of return arguments:\n\texpected: $expected_tis.str()\n\tgot: $got_tis.str()', return_stmt.pos) } for i, exp_ti in expected_tis { @@ -150,11 +165,11 @@ pub fn (c &Checker) check_return_stmt(return_stmt ast.Return) { } } -pub fn (c &Checker) check_array_init(array_init ast.ArrayInit) { - mut val_ti := types.void_ti +pub fn (c &Checker) array_init(array_init ast.ArrayInit) table.Type { + mut val_ti := table.void_type for i, expr in array_init.exprs { c.expr(expr) - ti := c.table.get_expr_ti(expr) + ti := c.expr(expr) // The first element's type if i == 0 { val_ti = ti @@ -164,6 +179,7 @@ pub fn (c &Checker) check_array_init(array_init ast.ArrayInit) { c.error('expected array element with type `$val_ti.name`', array_init.pos) } } + return array_init.ti } fn (c &Checker) stmt(node ast.Stmt) { @@ -174,10 +190,15 @@ fn (c &Checker) stmt(node ast.Stmt) { } } ast.Return { - c.check_return_stmt(it) + c.return_stmt(it) } ast.VarDecl { - c.expr(it.expr) + typ := c.expr(it.expr) + println('1111var decl $typ.name it.typ=$it.typ.name $it.pos.line_nr') + if it.typ.kind == .unresolved { + // it.ti = typ + println('VAR DECL UN!!!') + } } ast.ForStmt { c.expr(it.cond) @@ -201,42 +222,58 @@ fn (c &Checker) stmt(node ast.Stmt) { } } -fn (c &Checker) expr(node ast.Expr) { +pub fn (c &Checker) expr(node ast.Expr) table.Type { match node { ast.AssignExpr { c.check_assign_expr(it) } - // ast.IntegerLiteral {} + ast.IntegerLiteral { + return table.int_type + } // ast.FloatLiteral {} ast.PostfixExpr { - c.expr(it.expr) + return c.expr(it.expr) } + /* ast.UnaryExpr { c.expr(it.left) } - // ast.StringLiteral {} - ast.PrefixExpr { - c.expr(it.right) + */ + + ast.StringLiteral { + return table.string_type } - ast.BinaryExpr { - c.check_binary_expr(it) + ast.PrefixExpr { + return c.expr(it.right) + } + ast.InfixExpr { + return c.infix_expr(it) } ast.StructInit { - c.check_struct_init(it) + return c.check_struct_init(it) } ast.CallExpr { - c.check_call_expr(it) + return c.call_expr(it) } ast.MethodCallExpr { - c.check_method_call_expr(it) + return c.check_method_call_expr(it) } ast.ArrayInit { - c.check_array_init(it) + 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 table.void_type } - // ast.Ident {} // ast.BoolLiteral {} ast.SelectorExpr { - c.check_selector_expr(it) + return c.selector_expr(it) } ast.IndexExpr { c.expr(it.left) @@ -255,6 +292,7 @@ fn (c &Checker) expr(node ast.Expr) { } else {} } + return table.void_type } pub fn (c &Checker) error(s string, pos token.Position) { @@ -268,5 +306,6 @@ pub fn (c &Checker) error(s string, pos token.Position) { eprintln(final_msg_line) } */ + exit(1) } diff --git a/vlib/v/eval/eval.v b/vlib/v/eval/eval.v new file mode 100644 index 0000000000..413d26f784 --- /dev/null +++ b/vlib/v/eval/eval.v @@ -0,0 +1,104 @@ +// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. +module eval + +import ( + v.ast + v.checker + v.table +) + +pub type Object = int | string + +pub struct Eval { +mut: + checker checker.Checker + vars map[string]Var +} + +pub struct Var { + value Object +} + +pub fn (e mut Eval) eval(file ast.File, table &table.Table) string { + mut res := '' + e.checker = checker.new_checker(table) + for stmt in file.stmts { + res += e.stmt(stmt) + '\n' + } + return res.trim_space() +} + +fn print_object(o Object) { + match o { + int { + println(it) + } + else { + println('unknown object') + } + } +} + +pub fn (o Object) str() string { + match o { + int { + return it.str() + } + else { + println('unknown object') + } + } + return '' +} + +fn (e mut Eval) stmt(node ast.Stmt) string { + match node { + ast.ExprStmt { + o := e.expr(it.expr) + print('out: ') + print_object(o) + return o.str() + } + ast.VarDecl { + e.vars[it.name] = Var{ + value: e.expr(it.expr) + } + } + else {} + } + return '>>' +} + +fn (e mut Eval) expr(node ast.Expr) Object { + match node { + ast.IntegerLiteral { + return it.val + } + ast.Ident { + print_object(it.value) + // Find the variable + v := e.vars[it.name] + return v.value + } + ast.InfixExpr { + e.checker.infix_expr(it) + // println('bin $it.op') + left := e.expr(it.left) as int + right := e.expr(it.right) as int + match it.op { + .plus { + return left + right + } + .mul { + return left * right + } + else {} + } + } + else {} + } + return 0 + // return Object{} +} diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 1c77dc7ccc..ed54a76712 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -4,6 +4,7 @@ import ( strings v.ast v.table + v.checker // v.types term ) @@ -12,6 +13,7 @@ struct Gen { out strings.Builder definitions strings.Builder // typedefs, defines etc (everything that goes to the top of the file) table &table.Table + checker checker.Checker mut: fn_decl &ast.FnDecl // pointer to the FnDecl we are currently inside otherwise 0 } @@ -22,6 +24,8 @@ pub fn cgen(files []ast.File, table &table.Table) string { out: strings.new_builder(100) definitions: strings.new_builder(100) table: table + checker: checker.new_checker(table) // checker + fn_decl: 0 } for file in files { @@ -63,10 +67,11 @@ fn (g mut Gen) stmt(node ast.Stmt) { // t := g.table.get_type(arg.ti.idx) ti := g.table.refresh_ti(arg.ti) g.write(ti.name + ' ' + arg.name) + g.definitions.write(ti.name + ' ' + arg.name) if i < it.args.len - 1 { g.write(', ') + g.definitions.write(', ') } - g.definitions.write(ti.name + ' ' + arg.name) } g.writeln(') { ') if !is_main { @@ -82,12 +87,12 @@ fn (g mut Gen) stmt(node ast.Stmt) { g.fn_decl = 0 } ast.Return { - g.write('return ') + g.write('return') // multiple returns if it.exprs.len > 1 { // t := g.table.get_type(g.fn_decl.ti.idx) ti := g.table.refresh_ti(g.fn_decl.ti) - g.write('($ti.name){') + g.write(' ($ti.name){') for i, expr in it.exprs { g.write('.arg$i=') g.expr(expr) @@ -98,17 +103,20 @@ fn (g mut Gen) stmt(node ast.Stmt) { g.write('}') } // normal return - else { + else if it.exprs.len == 1 { + g.write(' ') g.expr(it.exprs[0]) } g.writeln(';') } ast.VarDecl { - mut ti := it.ti - if ti.kind == .unresolved { - ti = g.table.get_expr_ti(it.expr) + mut typ := it.typ + if typ.kind == .unresolved { + // g.write('/*unresolved*/') + // ti = table.void_type // g.table.get_expr_ti(it.expr) + typ = g.checker.expr(it.expr) } - g.write('$ti.name $it.name = ') + g.write('$typ.name $it.name = ') g.expr(it.expr) g.writeln(';') } @@ -177,6 +185,7 @@ fn (g mut Gen) expr(node ast.Expr) { g.expr(it.expr) g.write(it.op.str()) } + /* ast.UnaryExpr { // probably not :D if it.op in [.inc, .dec] { @@ -188,6 +197,8 @@ fn (g mut Gen) expr(node ast.Expr) { g.expr(it.left) } } + */ + ast.StringLiteral { g.write('tos3("$it.val")') } @@ -195,7 +206,7 @@ fn (g mut Gen) expr(node ast.Expr) { g.write(it.op.str()) g.expr(it.right) } - ast.BinaryExpr { + ast.InfixExpr { g.expr(it.left) if it.op == .dot { println('!! dot') diff --git a/vlib/v/gen/jsgen.v b/vlib/v/gen/jsgen.v index ba3b790f93..71c8f644ae 100644 --- a/vlib/v/gen/jsgen.v +++ b/vlib/v/gen/jsgen.v @@ -8,7 +8,7 @@ import ( ) struct JsGen { - out strings.Builder + out strings.Builder table &table.Table } @@ -51,17 +51,15 @@ fn (g mut JsGen) stmt(node ast.Stmt) { } ast.Return { g.write('return ') - if it.exprs.len > 0 { - - } + if it.exprs.len > 0 {} else { g.expr(it.exprs[0]) } g.writeln(';') } ast.VarDecl { - ti := g.table.refresh_ti(it.ti) - g.write('var /* $ti.name */ $it.name = ') + typ := g.table.refresh_ti(it.typ) + g.write('var /* $typ.name */ $it.name = ') g.expr(it.expr) g.writeln(';') } @@ -106,14 +104,17 @@ fn (g mut JsGen) expr(node ast.Expr) { ast.FloatLiteral { g.write(it.val) } + /* ast.UnaryExpr { g.expr(it.left) g.write(' $it.op ') } + */ + ast.StringLiteral { g.write('tos3("$it.val")') } - ast.BinaryExpr { + ast.InfixExpr { g.expr(it.left) g.write(' $it.op.str() ') g.expr(it.right) diff --git a/vlib/v/gen/tests/1.c b/vlib/v/gen/tests/1.c index 16c2803c82..9eaf8146c7 100644 --- a/vlib/v/gen/tests/1.c +++ b/vlib/v/gen/tests/1.c @@ -4,19 +4,22 @@ int get_int2(); void myuser(); multi_return_int_string multi_return(); void variadic(variadic_int a); +void ensure_cap(int required, int cap); typedef struct { int age; } User; int main() { -int a = 10; -a++; -int negative = -a; -a == 1; -foo(3); -int ak = 10; -return 0; + int a = 10; + a++; + int negative = -a; + 2 < 3; + a == 1; + a++; + foo(3); + int ak = 10; + return 0; } void foo(int a) { @@ -31,7 +34,19 @@ i < 10; i++; 1, 2, 3, }); int number = nums[0]; + array_bool bools = new_array_from_c_array(2, 2, sizeof(array_bool), { + true, false, + }); + bool b = bools[0]; + array_string mystrings = new_array_from_c_array(2, 2, sizeof(array_string), { + tos3("a"), tos3("b"), + }); + string s = mystrings[0]; + int x = 0; + x = get_int2(); int n = get_int2(); + bool q = true || false; + bool b2 = bools[0] || true; } int get_int(string a) { @@ -55,8 +70,14 @@ void myuser() { } multi_return_int_string multi_return() { -return (multi_return_int_string){.arg0=4,.arg1=tos3("four")}; -} + return (multi_return_int_string){.arg0=4,.arg1=tos3("four")}; +} void variadic(variadic_int a) { } + +void ensure_cap(int required, int cap) { + if (required < cap) { + return; + } +} diff --git a/vlib/v/gen/tests/1.vv b/vlib/v/gen/tests/1.vv index 90c0bc9de4..73cdeabb47 100644 --- a/vlib/v/gen/tests/1.vv +++ b/vlib/v/gen/tests/1.vv @@ -5,12 +5,14 @@ struct User { age int } -// lol fn main() { a := 10 + //bb := 2 + 'hi' a++ negative := -a + 2 < 3 a == 1 + a++ foo(3) ak := 10 } @@ -32,7 +34,16 @@ fn foo(a int) { } nums := [1,2,3] number := nums[0] + bools := [true, false] + b := bools[0] + mystrings := ['a', 'b'] + s := mystrings[0] + ////////// + mut x := 0 + x=get_int2() n := get_int2() + q := true || false + b2 := bools[0] || true } fn get_int(a string) int { @@ -41,6 +52,7 @@ fn get_int(a string) int { fn get_int2() int { a := 'hello' + //return get_int('sdf') return get_int(a) } @@ -60,3 +72,10 @@ fn multi_return() (int,string) { fn variadic(a ...int) { } +fn ensure_cap(required int, cap int) { + if required < cap { + return + } +} + + diff --git a/vlib/v/gen/x64/gen.v b/vlib/v/gen/x64/gen.v index 1682d18982..b141f79ab2 100644 --- a/vlib/v/gen/x64/gen.v +++ b/vlib/v/gen/x64/gen.v @@ -344,11 +344,14 @@ fn (g mut Gen) expr(node ast.Expr) { ast.AssignExpr {} ast.IntegerLiteral {} ast.FloatLiteral {} + /* ast.UnaryExpr { g.expr(it.left) } + */ + ast.StringLiteral {} - ast.BinaryExpr {} + ast.InfixExpr {} // `user := User{name: 'Bob'}` ast.StructInit {} ast.CallExpr { diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index e87282d616..0bfa875044 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -6,10 +6,9 @@ module parser import ( v.ast v.table - v.types ) -pub fn (p mut Parser) call_expr() (ast.CallExpr,types.TypeIdent) { +pub fn (p mut Parser) call_expr() (ast.CallExpr,table.Type) { tok := p.tok fn_name := p.check_name() p.check(.lpar) @@ -27,16 +26,15 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,types.TypeIdent) { name: fn_name args: args // tok: tok - pos: tok.position() + pos: tok.position() } - mut ti := types.unresolved_ti + mut ti := table.unresolved_type if f := p.table.find_fn(fn_name) { - ti = f.return_ti + ti = f.return_type } println('adding call_expr check $fn_name') - - return node, ti + return node,ti } pub fn (p mut Parser) call_args() []ast.Expr { @@ -49,7 +47,7 @@ pub fn (p mut Parser) call_args() []ast.Expr { } } p.check(.rpar) - return args // ,types.void_ti + return args // ,table.void_ti } fn (p mut Parser) fn_decl() ast.FnDecl { @@ -62,7 +60,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl { // Receiver? mut rec_name := '' mut is_method := false - mut rec_ti := types.void_ti + mut rec_ti := table.void_type if p.tok.kind == .lpar { is_method = true p.next() @@ -73,7 +71,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl { rec_ti = p.parse_ti() p.table.register_var(table.Var{ name: rec_name - ti: rec_ti + typ: rec_ti }) p.check(.rpar) } @@ -94,7 +92,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl { for arg_name in arg_names { arg := table.Var{ name: arg_name - ti: ti + typ: ti } args << arg p.table.register_var(arg) @@ -112,16 +110,19 @@ fn (p mut Parser) fn_decl() ast.FnDecl { } p.check(.rpar) // Return type - mut ti := types.void_ti + mut typ := table.void_type if p.tok.kind in [.name, .lpar] { - ti = p.parse_ti() - p.return_ti = ti + typ = p.parse_ti() + p.return_type = typ + } + else { + p.return_type = table.void_type } if is_method { ok := p.table.register_method(rec_ti, table.Fn{ name: name args: args - return_ti: ti + return_type: typ }) if !ok { p.error('expected Struct') @@ -131,14 +132,14 @@ fn (p mut Parser) fn_decl() ast.FnDecl { p.table.register_fn(table.Fn{ name: name args: args - return_ti: ti + return_type: typ }) } stmts := p.parse_block() return ast.FnDecl{ name: name stmts: stmts - ti: ti + ti: typ args: ast_args is_pub: is_pub receiver: ast.Field{ @@ -161,4 +162,5 @@ pub fn (p &Parser) check_fn_calls() { // println('IN AST typ=' + call.typ.name) } */ + } diff --git a/vlib/v/parser/a_type.v b/vlib/v/parser/parse_type.v similarity index 54% rename from vlib/v/parser/a_type.v rename to vlib/v/parser/parse_type.v index 16602fbc61..dbca3e2289 100644 --- a/vlib/v/parser/a_type.v +++ b/vlib/v/parser/parse_type.v @@ -2,9 +2,12 @@ module parser // Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. -import v.types -pub fn (p mut Parser) parse_array_ti(nr_muls int) types.TypeIdent { +import ( + v.table +) + +pub fn (p mut Parser) parse_array_ti(nr_muls int) table.Type { p.check(.lsbr) // fixed array if p.tok.kind == .number { @@ -12,7 +15,7 @@ pub fn (p mut Parser) parse_array_ti(nr_muls int) types.TypeIdent { p.check(.rsbr) elem_ti := p.parse_ti() idx,name := p.table.find_or_register_array_fixed(&elem_ti, size, 1) - return types.new_ti(.array_fixed, name, idx, nr_muls) + return table.new_type(.array_fixed, name, idx, nr_muls) } // array p.check(.rsbr) @@ -24,22 +27,22 @@ pub fn (p mut Parser) parse_array_ti(nr_muls int) types.TypeIdent { nr_dims++ } idx,name := p.table.find_or_register_array(&elem_ti, nr_dims) - return types.new_ti(.array, name, idx, nr_muls) + return table.new_type(.array, name, idx, nr_muls) } -pub fn (p mut Parser) parse_map_ti(nr_muls int) types.TypeIdent { +pub fn (p mut Parser) parse_map_ti(nr_muls int) table.Type { p.next() p.check(.lsbr) key_ti := p.parse_ti() p.check(.rsbr) value_ti := p.parse_ti() idx,name := p.table.find_or_register_map(&key_ti, &value_ti) - return types.new_ti(.map, name, idx, nr_muls) + return table.new_type(.map, name, idx, nr_muls) } -pub fn (p mut Parser) parse_multi_return_ti() types.TypeIdent { +pub fn (p mut Parser) parse_multi_return_ti() table.Type { p.check(.lpar) - mut mr_tis := []types.TypeIdent + mut mr_tis := []table.Type for { mr_ti := p.parse_ti() mr_tis << mr_ti @@ -52,17 +55,17 @@ pub fn (p mut Parser) parse_multi_return_ti() types.TypeIdent { } p.check(.rpar) idx,name := p.table.find_or_register_multi_return(mr_tis) - return types.new_ti(.multi_return, name, idx, 0) + return table.new_type(.multi_return, name, idx, 0) } -pub fn (p mut Parser) parse_variadic_ti() types.TypeIdent { +pub fn (p mut Parser) parse_variadic_ti() table.Type { p.check(.ellipsis) variadic_ti := p.parse_ti() idx,name := p.table.find_or_register_variadic(&variadic_ti) - return types.new_ti(.variadic, name, idx, 0) + return table.new_type(.variadic, name, idx, 0) } -pub fn (p mut Parser) parse_ti() types.TypeIdent { +pub fn (p mut Parser) parse_ti() table.Type { mut nr_muls := 0 for p.tok.kind == .amp { p.check(.amp) @@ -98,65 +101,66 @@ pub fn (p mut Parser) parse_ti() types.TypeIdent { return p.parse_map_ti(nr_muls) } 'voidptr' { - return types.new_ti(.voidptr, 'voidptr', types.voidptr_type_idx, nr_muls) + return table.new_type(.voidptr, 'voidptr', table.voidptr_type_idx, nr_muls) } 'byteptr' { - return types.new_ti(.byteptr, 'byteptr', types.byteptr_type_idx, nr_muls) + return table.new_type(.byteptr, 'byteptr', table.byteptr_type_idx, nr_muls) } 'charptr' { - return types.new_ti(.charptr, 'charptr', types.charptr_type_idx, nr_muls) + return table.new_type(.charptr, 'charptr', table.charptr_type_idx, nr_muls) } 'i8' { - return types.new_ti(.i8, 'i8', types.i8_type_idx, nr_muls) + return table.new_type(.i8, 'i8', table.i8_type_idx, nr_muls) } 'i16' { - return types.new_ti(.i16, 'i16', types.i16_type_idx, nr_muls) + return table.new_type(.i16, 'i16', table.i16_type_idx, nr_muls) } 'int' { - return types.new_ti(.int, 'int', types.int_type_idx, nr_muls) + return table.new_type(.int, 'int', table.int_type_idx, nr_muls) } 'i64' { - return types.new_ti(.i64, 'i64', types.i64_type_idx, nr_muls) + return table.new_type(.i64, 'i64', table.i64_type_idx, nr_muls) } 'byte' { - return types.new_ti(.byte, 'byte', types.byte_type_idx, nr_muls) + return table.new_type(.byte, 'byte', table.byte_type_idx, nr_muls) } 'u16' { - return types.new_ti(.u16, 'u16', types.u16_type_idx, nr_muls) + return table.new_type(.u16, 'u16', table.u16_type_idx, nr_muls) } 'u32' { - return types.new_ti(.u32, 'u32', types.u32_type_idx, nr_muls) + return table.new_type(.u32, 'u32', table.u32_type_idx, nr_muls) } 'u64' { - return types.new_ti(.u64, 'u64', types.u64_type_idx, nr_muls) + return table.new_type(.u64, 'u64', table.u64_type_idx, nr_muls) } 'f32' { - return types.new_ti(.f32, 'f32', types.f32_type_idx, nr_muls) + return table.new_type(.f32, 'f32', table.f32_type_idx, nr_muls) } 'f64' { - return types.new_ti(.f64, 'f64', types.f64_type_idx, nr_muls) + return table.new_type(.f64, 'f64', table.f64_type_idx, nr_muls) } 'string' { - return types.new_ti(.string, 'string', types.string_type_idx, nr_muls) + return table.new_type(.string, 'string', table.string_type_idx, nr_muls) } 'char' { - return types.new_ti(.char, 'char', types.charptr_type_idx, nr_muls) + return table.new_type(.char, 'char', table.charptr_type_idx, nr_muls) } 'bool' { - return types.new_ti(.bool, 'bool', types.bool_type_idx, nr_muls) + return table.new_type(.bool, 'bool', table.bool_type_idx, nr_muls) } // struct / enum / placeholder else { // struct / enum mut idx := p.table.find_type_idx(name) if idx > 0 { - return types.new_ti(p.table.types[idx].kind, name, idx, nr_muls) + return table.new_type(p.table.types[idx].kind, name, idx, nr_muls) } // not found - add placeholder idx = p.table.add_placeholder_type(name) - return types.new_ti(.placeholder, name, idx, nr_muls) + return table.new_type(.placeholder, name, idx, nr_muls) } } } } } + diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 5ae1afe29d..01fb92cefb 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -8,10 +8,10 @@ import ( v.ast v.token v.table - v.types term os ) + const ( colored_output = term.can_show_color_on_stderr() ) @@ -23,20 +23,21 @@ type InfixParseFn fn(e ast.Expr)ast.Expr type PostfixParseFn fn()ast.Expr struct Parser { - scanner &scanner.Scanner - file_name string + scanner &scanner.Scanner + file_name string mut: - tok token.Token - peek_tok token.Token + tok token.Token + peek_tok token.Token // vars []string - table &table.Table - return_ti types.TypeIdent - is_c bool + table &table.Table + return_type table.Type // current function's return type + is_c bool // // prefix_parse_fns []PrefixParseFn - inside_if bool + inside_if bool } +// for tests pub fn parse_stmt(text string, table &table.Table) ast.Stmt { s := scanner.new_scanner(text) mut p := Parser{ @@ -60,22 +61,15 @@ pub fn parse_file(path string, table &table.Table) ast.File { file_name: path } p.read_first_token() - // module decl - module_decl := if p.tok.kind == .key_module { - p.module_decl() - } else { - ast.Module{ - name: 'main' - } - } + module_decl := if p.tok.kind == .key_module { p.module_decl() } else { ast.Module{name: 'main' + } } // imports mut imports := []ast.Import for p.tok.kind == .key_import { imports << p.import_stmt() } // TODO: import only mode - for { // res := s.scan() if p.tok.kind == .eof { @@ -88,9 +82,9 @@ pub fn parse_file(path string, table &table.Table) ast.File { // println('nr stmts = $stmts.len') // println(stmts[0]) return ast.File{ - mod: module_decl + mod: module_decl imports: imports - stmts: stmts + stmts: stmts } } @@ -168,12 +162,12 @@ pub fn (p mut Parser) top_stmt() ast.Stmt { p.error('wrong pub keyword usage') return ast.Stmt{} } - // .key_enum { - // return p.enum_decl() - // } - // .key_type { - // return p.type_decl() - // } + // .key_enum { + // return p.enum_decl() + // } + // .key_type { + // return p.type_decl() + // } } } .key_const { @@ -227,7 +221,7 @@ pub fn (p mut Parser) stmt() ast.Stmt { pub fn (p mut Parser) assign_expr(left ast.Expr) ast.AssignExpr { op := p.tok.kind p.next() - val, _ := p.expr(0) + val,_ := p.expr(0) node := ast.AssignExpr{ left: left val: val @@ -270,7 +264,8 @@ pub fn (p &Parser) error(s string) { final_msg_line := '$p.file_name:$p.tok.line_nr: error: $s' if colored_output { eprintln(term.bold(term.red(final_msg_line))) - }else{ + } + else { eprintln(final_msg_line) } exit(1) @@ -280,7 +275,8 @@ pub fn (p &Parser) error_at_line(s string, line_nr int) { final_msg_line := '$p.file_name:$line_nr: error: $s' if colored_output { eprintln(term.bold(term.red(final_msg_line))) - }else{ + } + else { eprintln(final_msg_line) } exit(1) @@ -290,15 +286,16 @@ pub fn (p &Parser) warn(s string) { final_msg_line := '$p.file_name:$p.tok.line_nr: warning: $s' if colored_output { eprintln(term.bold(term.blue(final_msg_line))) - }else{ + } + else { eprintln(final_msg_line) } } -pub fn (p mut Parser) name_expr() (ast.Expr,types.TypeIdent) { +pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) { mut node := ast.Expr{} - // mut ti := types.void_ti - mut ti := types.unresolved_ti + // mut typ := table.void_ti + mut typ := table.unresolved_type if p.tok.lit == 'C' { p.next() p.check(.dot) @@ -310,14 +307,14 @@ pub fn (p mut Parser) name_expr() (ast.Expr,types.TypeIdent) { // fn call if p.peek_tok.kind == .lpar { println('calling $p.tok.lit') - x, ti2 := p.call_expr() // TODO `node,typ :=` should work + x,ti2 := p.call_expr() // TODO `node,typ :=` should work node = x - ti = ti2 + typ = ti2 } // struct init - else if p.peek_tok.kind == .lcbr && !p.inside_if { - ti = p.parse_ti() - // println('sturct init ti=$ti.name') + else if p.peek_tok.kind == .lcbr && (p.tok.lit[0].is_capital() || p.tok.lit in ['array', 'string']) { + typ = p.parse_ti() + // p.warn('struct init typ=$typ.name') p.check(.lcbr) mut field_names := []string mut exprs := []ast.Expr @@ -329,13 +326,14 @@ pub fn (p mut Parser) name_expr() (ast.Expr,types.TypeIdent) { exprs << expr } node = ast.StructInit{ - ti: ti + ti: typ exprs: exprs fields: field_names pos: p.tok.position() } p.check(.rcbr) } + // variable else { // p.warn('name ') // left := p.parse_ident() @@ -346,33 +344,36 @@ pub fn (p mut Parser) name_expr() (ast.Expr,types.TypeIdent) { p.error('name expr unknown variable `$p.tok.lit`') exit(0) } - ti = var.ti + typ = var.typ ident.kind = .variable - ident.info = ast.IdentVar { - ti: ti - expr: var.expr + ident.info = ast.IdentVar{ + typ: typ + name: ident.name + // expr: p.expr(0)// var.expr + } // ident.ti = ti node = ident p.next() } - return node,ti + return node,typ } -pub fn (p mut Parser) expr(precedence int) (ast.Expr,types.TypeIdent) { - mut ti := types.void_ti +pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) { + // println('\n\nparser.expr()') + mut typ := table.void_type mut node := ast.Expr{} // Prefix match p.tok.kind { .name { - node,ti = p.name_expr() + node,typ = p.name_expr() } .str { - node,ti = p.string_expr() + node,typ = p.string_expr() } // -1, -a etc .minus, .amp { - node,ti = p.prefix_expr() + node,typ = p.prefix_expr() } // .amp { // p.next() @@ -381,22 +382,22 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,types.TypeIdent) { node = ast.BoolLiteral{ val: p.tok.kind == .key_true } - ti = types.bool_ti + typ = table.bool_type p.next() } .number { - node,ti = p.parse_number_literal() + node,typ = p.parse_number_literal() } .lpar { p.check(.lpar) - node,ti = p.expr(0) + node,typ = p.expr(0) p.check(.rpar) } .key_if { - node,ti = p.if_expr() + node,typ = p.if_expr() } .lsbr { - node,ti = p.array_init() + node,typ = p.array_init() } else { p.error('expr(): bad token `$p.tok.str()`') @@ -408,13 +409,27 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,types.TypeIdent) { node = p.assign_expr(node) } else if p.tok.kind == .dot { - node,ti = p.dot_expr(node, ti) + node,typ = p.dot_expr(node, typ) } else if p.tok.kind == .lsbr { - node,ti = p.index_expr(node) + // 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) } else if p.tok.kind.is_infix() { - node,ti = p.infix_expr(node) + node,typ = p.infix_expr(node) } // Postfix else if p.tok.kind in [.inc, .dec] { @@ -423,16 +438,16 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,types.TypeIdent) { expr: node } p.next() - return node,ti + return node,typ } else { - return node,ti + return node,typ } } - return node,ti + return node,typ } -fn (p mut Parser) prefix_expr() (ast.Expr,types.TypeIdent) { +fn (p mut Parser) prefix_expr() (ast.Expr,table.Type) { op := p.tok.kind p.next() right,ti := p.expr(1) @@ -444,27 +459,29 @@ fn (p mut Parser) prefix_expr() (ast.Expr,types.TypeIdent) { return expr,ti } -fn (p mut Parser) index_expr(left ast.Expr) (ast.Expr,types.TypeIdent) { +fn (p mut Parser) index_expr(left ast.Expr) ast.Expr { + // ,table.Type) { // println('index expr$p.tok.str() line=$p.tok.line_nr') p.next() - println('start expr') - index,_ := p.expr(0) - println('end expr') + println('start index expr') + index,typ := p.expr(0) + println('end expr typ=$typ.name') p.check(.rsbr) println('got ]') - ti := types.int_ti + // /ti := table.int_type mut node := ast.Expr{} node = ast.IndexExpr{ left: left index: index } - return node,ti + return node + // /return node,ti } -fn (p mut Parser) dot_expr(left ast.Expr, left_ti &types.TypeIdent) (ast.Expr,types.TypeIdent) { +fn (p mut Parser) dot_expr(left ast.Expr, left_ti &table.Type) (ast.Expr,table.Type) { p.next() field_name := p.check_name() - ti := types.unresolved_ti + ti := table.unresolved_type // Method call if p.tok.kind == .lpar { p.next() @@ -477,9 +494,8 @@ fn (p mut Parser) dot_expr(left ast.Expr, left_ti &types.TypeIdent) (ast.Expr,ty } mut node := ast.Expr{} node = mcall_expr - return node, ti + return node,ti } - sel_expr := ast.SelectorExpr{ expr: left field: field_name @@ -487,10 +503,10 @@ fn (p mut Parser) dot_expr(left ast.Expr, left_ti &types.TypeIdent) (ast.Expr,ty } mut node := ast.Expr{} node = sel_expr - return node, ti + return node,ti } -fn (p mut Parser) infix_expr(left ast.Expr) (ast.Expr,types.TypeIdent) { +fn (p mut Parser) infix_expr(left ast.Expr) (ast.Expr,table.Type) { op := p.tok.kind // mut typ := p. // println('infix op=$op.str()') @@ -498,12 +514,13 @@ fn (p mut Parser) infix_expr(left ast.Expr) (ast.Expr,types.TypeIdent) { p.next() right,mut ti := p.expr(precedence) if op.is_relational() { - ti = types.bool_ti + ti = table.bool_type } mut expr := ast.Expr{} - expr = ast.BinaryExpr{ + expr = ast.InfixExpr{ left: left right: right + right_type: ti op: op pos: p.tok.position() } @@ -549,7 +566,7 @@ fn (p mut Parser) for_statement() ast.Stmt { } p.check(.semicolon) if p.tok.kind != .semicolon { - mut typ := types.TypeIdent{} + mut typ := table.Type{} cond,typ = p.expr(0) if typ.kind != .bool { p.error('non-bool used as for condition') @@ -585,7 +602,7 @@ fn (p mut Parser) for_statement() ast.Stmt { } // `for cond {` cond,ti := p.expr(0) - if !p.table.check(types.bool_ti, ti) { + if !p.table.check(table.bool_type, ti) { p.error('non-bool used as for condition') } stmts := p.parse_block() @@ -595,16 +612,17 @@ fn (p mut Parser) for_statement() ast.Stmt { } } -fn (p mut Parser) if_expr() (ast.Expr,types.TypeIdent) { +fn (p mut Parser) if_expr() (ast.Expr,table.Type) { p.inside_if = true // defer { // } mut node := ast.Expr{} p.check(.key_if) cond,cond_ti := p.expr(0) - // if !p.table.check(types.bool_ti, cond_ti) { + p.inside_if = false + // if !p.table.check(table.bool_ti, cond_ti) { if cond_ti.kind != .bool { - p.error('non-bool used as if condition') + p.error('non-bool (`$cond_ti.name`) used as if condition') } stmts := p.parse_block() mut else_stmts := []ast.Stmt @@ -612,7 +630,7 @@ fn (p mut Parser) if_expr() (ast.Expr,types.TypeIdent) { p.check(.key_else) else_stmts = p.parse_block() } - mut ti := types.void_ti + mut ti := table.void_type // mut left := ast.Expr{} // If the last statement is an expression, return its type match stmts[stmts.len - 1] { @@ -632,18 +650,17 @@ fn (p mut Parser) if_expr() (ast.Expr,types.TypeIdent) { // left: left } - p.inside_if = false return node,ti } -fn (p mut Parser) string_expr() (ast.Expr,types.TypeIdent) { +fn (p mut Parser) string_expr() (ast.Expr,table.Type) { mut node := ast.Expr{} node = ast.StringLiteral{ val: p.tok.lit } if p.peek_tok.kind != .str_dollar { p.next() - return node,types.string_ti + return node,table.string_type } // Handle $ interpolation for p.tok.kind == .str { @@ -654,14 +671,14 @@ fn (p mut Parser) string_expr() (ast.Expr,types.TypeIdent) { p.check(.str_dollar) p.expr(0) } - return node,types.string_ti + return node,table.string_type } -fn (p mut Parser) array_init() (ast.Expr,types.TypeIdent) { +fn (p mut Parser) array_init() (ast.Expr,table.Type) { p.check(.lsbr) - mut val_ti := types.void_ti + mut val_ti := table.void_type mut exprs := []ast.Expr - for i:=0; p.tok.kind != .rsbr; i++ { + for i := 0; p.tok.kind != .rsbr; i++ { expr,ti := p.expr(0) exprs << expr if i == 0 { @@ -672,7 +689,7 @@ fn (p mut Parser) array_init() (ast.Expr,types.TypeIdent) { } } type_idx,type_name := p.table.find_or_register_array(val_ti, 1) - array_ti := types.new_ti(.array, type_name, type_idx, 0) + array_ti := table.new_type(.array, type_name, type_idx, 0) mut node := ast.Expr{} node = ast.ArrayInit{ ti: array_ti @@ -683,23 +700,23 @@ fn (p mut Parser) array_init() (ast.Expr,types.TypeIdent) { return node,array_ti } -fn (p mut Parser) parse_number_literal() (ast.Expr,types.TypeIdent) { +fn (p mut Parser) parse_number_literal() (ast.Expr,table.Type) { lit := p.tok.lit mut node := ast.Expr{} - mut ti := types.int_ti + mut ti := table.int_type if lit.contains('.') { node = ast.FloatLiteral{ // val: lit.f64() val: lit } - // ti = types.new_builtin_ti(.f64, 0) - ti = types.new_ti(.f64, 'f64', types.f64_type_idx, 0) + // ti = table.new_builtin_ti(.f64, 0) + ti = table.new_type(.f64, 'f64', table.f64_type_idx, 0) } else { node = ast.IntegerLiteral{ val: lit.int() } - // ti = types.int_ti + // ti = table.int_ti } p.next() return node,ti @@ -736,14 +753,15 @@ fn (p mut Parser) import_stmt() []ast.Import { imports << p.parse_import() } p.check(.rpar) - } else { + } + else { imports << p.parse_import() } return imports } // TODO -//fn (p mut Parser) const_decl() ast... { +// fn (p mut Parser) const_decl() ast... { fn (p mut Parser) const_decl() ast.Stmt { p.check(.key_const) p.check(.lpar) @@ -751,7 +769,7 @@ fn (p mut Parser) const_decl() ast.Stmt { name := p.check_name() println('const: $name') p.check(.assign) - _, _ := p.expr(0) + _,_ := p.expr(0) // expr, ti := p.expr(0) } p.check(.rpar) @@ -767,7 +785,7 @@ fn (p mut Parser) struct_decl() ast.StructDecl { name := p.check_name() p.check(.lcbr) mut ast_fields := []ast.Field - mut fields := []types.Field + mut fields := []table.Field for p.tok.kind != .rcbr { if p.tok.kind == .key_pub { p.check(.key_pub) @@ -779,9 +797,10 @@ fn (p mut Parser) struct_decl() ast.StructDecl { name: field_name ti: ti } - fields << types.Field{ + fields << table.Field{ name: field_name // type_idx: ti.idx + ti: ti } } @@ -789,7 +808,7 @@ fn (p mut Parser) struct_decl() ast.StructDecl { p.table.register_type(table.Type{ kind: .struct_ name: name - info: types.Struct{ + info: table.Struct{ fields: fields } }) @@ -806,10 +825,15 @@ fn (p mut Parser) return_stmt() ast.Return { // return expressions mut exprs := []ast.Expr // return type idents - // mut got_tis := []types.TypeIdent + // mut got_tis := []table.Type + if p.return_type.idx == table.void_type_idx { + return ast.Return{ + pos: p.tok.position() + } + } for { // expr,ti := p.expr(0) - expr, _ := p.expr(0) + expr,_ := p.expr(0) exprs << expr // got_tis << ti if p.tok.kind == .comma { @@ -821,7 +845,7 @@ fn (p mut Parser) return_stmt() ast.Return { } // TODO: consider non deferred stmt := ast.Return{ - expected_ti: p.return_ti + expected_ti: p.return_type exprs: exprs pos: p.tok.position() } @@ -841,29 +865,30 @@ fn (p mut Parser) var_decl() ast.VarDecl { } name := p.tok.lit p.read_first_token() - expr, ti := p.expr(token.lowest_prec) + expr,typ := p.expr(token.lowest_prec) if _ := p.table.find_var(name) { p.error('redefinition of `$name`') } p.table.register_var(table.Var{ name: name is_mut: is_mut - expr: expr - ti: ti + // expr: expr + + typ: typ }) + p.warn('var decl name=$name typ=$typ.name') // println(p.table.names) node := ast.VarDecl{ name: name expr: expr // p.expr(token.lowest_prec) + is_mut: is_mut - ti: ti + typ: typ pos: p.tok.position() } return node } - - fn verror(s string) { println(s) exit(1) diff --git a/vlib/v/parser/parser_test.v b/vlib/v/parser/parser_test.v index 8252a4ad2d..90c21895f3 100644 --- a/vlib/v/parser/parser_test.v +++ b/vlib/v/parser/parser_test.v @@ -5,9 +5,49 @@ import ( v.gen v.table v.checker + v.eval term ) +fn test_eval() { + inputs := [ + // + '2+3', + '4', + 'x := 10', + 'x', + 'x + 1', + 'y := 2', + 'x * y', // 20 + // + ] + expected := [ + // + '5', + '4', + '>>', + '10', + '11', + '>>', + '20', + // + ] + table := table.new_table() + mut stmts := []ast.Stmt + for input in inputs { + stmts << parse_stmt(input, table) + } + file := ast.File{ + stmts: stmts + } + mut ev := eval.Eval{} + s := ev.eval(file, table) + println('eval done') + println(s) + assert s == expected.join('\n') + exit(0) +} + fn test_parse_file() { if true { return @@ -55,7 +95,9 @@ fn test_one() { } fn test_parse_expr() { + println('SDFSDFSDF') input := ['1 == 1', + '234234', '2 * 8 + 3', 'a := 3', 'a++', @@ -79,7 +121,8 @@ fn test_parse_expr() { '1.2 + 3.4', '4 + 4', '1 + 2 * 5', - '-a', + '-a+1', + '2+2', /* /* '(2 * 3) / 2', @@ -93,6 +136,7 @@ fn test_parse_expr() { ] expecting := ['1 == 1;', + '234234;', '2 * 8 + 3;', 'int a = 3;', 'a++;', @@ -116,13 +160,14 @@ fn test_parse_expr() { '1.2 + 3.4;', '4 + 4;', '1 + 2 * 5;', - '-a;', + '-a + 1;', + '2 + 2;', ] mut e := []ast.Stmt table := table.new_table() mut checker := checker.new_checker(table) for s in input { - // println('\n\nst="$s"') + println('\n\nst="$s"') e << parse_stmt(s, table) } program := ast.File{ diff --git a/vlib/v/types/types.v b/vlib/v/table/atypes.v similarity index 50% rename from vlib/v/types/types.v rename to vlib/v/table/atypes.v index 183d461441..592963522c 100644 --- a/vlib/v/types/types.v +++ b/vlib/v/table/atypes.v @@ -1,7 +1,21 @@ -// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved. +// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. -module types +module table + +pub type TypeInfo = Array | ArrayFixed | Map | Struct | MultiReturn | Variadic + +pub struct Type { +pub: + idx int + parent_idx int +mut: + info TypeInfo + kind Kind + name string + methods []Fn + nr_muls int +} pub const ( void_type_idx = 1 @@ -50,23 +64,53 @@ pub enum Kind { map multi_return variadic - unresolved + unresolved } -pub type TypeInfo = Array | ArrayFixed | Map | Struct | MultiReturn | Variadic +pub const ( + unresolved_type = Type{ + kind: .unresolved + name: 'unresolved' + } + void_type = Type{ + kind: .void + name: 'void' + idx: void_type_idx + } + int_type = Type{ + kind: .int + name: 'int' + idx: int_type_idx + } + string_type = Type{ + kind: .string + name: 'string' + idx: string_type_idx + } + bool_type = Type{ + kind: .bool + name: 'bool' + idx: bool_type_idx + } +) +/* +pub fn (t Type) str() string { + return t.name +} +*/ -pub struct TypeIdent { -pub: - idx int -mut: - kind Kind - name string - nr_muls int + +pub fn (t &Type) str() string { + mut muls := '' + for _ in 0 .. t.nr_muls { + muls += '&' + } + // return '$muls$ti.name' + return '$muls$t.idx' } -[inline] -pub fn new_ti(kind Kind, name string, idx int, nr_muls int) TypeIdent { - return TypeIdent{ +pub fn new_type(kind Kind, name string, idx int, nr_muls int) Type { + return Type{ idx: idx kind: kind name: name @@ -74,53 +118,103 @@ pub fn new_ti(kind Kind, name string, idx int, nr_muls int) TypeIdent { } } -// [inline] -// pub fn new_builtin_ti(kind Kind, nr_muls int) TypeIdent { -// return TypeIdent{ -// idx: -int(kind) - 1 -// kind: kind -// name: kind.str() -// nr_muls: nr_muls -// } -// } - -pub const ( - unresolved_ti = new_ti(.unresolved, 'unresolved', 0, 0) - void_ti = new_ti(.void, 'void', void_type_idx, 0) - int_ti = new_ti(.int, 'int', int_type_idx, 0) - string_ti = new_ti(.string, 'string', string_type_idx, 0) - bool_ti = new_ti(.bool, 'bool', bool_type_idx, 0) -) +pub fn (t mut Table) register_builtin_types() { + // reserve index 0 so nothing can go there + // save index check, 0 will mean not found + t.register_type(Type{ + kind: .placeholder + name: 'reserved_0' + }) + t.register_type(Type{ + kind: .void + name: 'void' + }) + t.register_type(Type{ + kind: .voidptr + name: 'voidptr' + }) + t.register_type(Type{ + kind: .charptr + name: 'charptr' + }) + t.register_type(Type{ + kind: .byteptr + name: 'byteptr' + }) + t.register_type(Type{ + kind: .i8 + name: 'i8' + }) + t.register_type(Type{ + kind: .i16 + name: 'i16' + }) + t.register_type(Type{ + kind: .int + name: 'int' + }) + t.register_type(Type{ + kind: .i64 + name: 'i64' + }) + t.register_type(Type{ + kind: .u16 + name: 'u16' + }) + t.register_type(Type{ + kind: .u32 + name: 'u32' + }) + t.register_type(Type{ + kind: .u64 + name: 'u64' + }) + t.register_type(Type{ + kind: .f32 + name: 'f32' + }) + t.register_type(Type{ + kind: .f64 + name: 'f64' + }) + t.register_type(Type{ + kind: .string + name: 'string' + }) + t.register_type(Type{ + kind: .char + name: 'char' + }) + t.register_type(Type{ + kind: .byte + name: 'byte' + }) + t.register_type(Type{ + kind: .bool + name: 'bool' + }) +} [inline] -pub fn (ti &TypeIdent) is_ptr() bool { +pub fn (ti &Type) is_ptr() bool { return ti.nr_muls > 0 } [inline] -pub fn (ti &TypeIdent) is_int() bool { +pub fn (ti &Type) is_int() bool { return ti.kind in [.i8, .i16, .int, .i64, .byte, .u16, .u32, .u64] } [inline] -pub fn (ti &TypeIdent) is_float() bool { +pub fn (ti &Type) is_float() bool { return ti.kind in [.f32, .f64] } [inline] -pub fn (ti &TypeIdent) is_number() bool { +pub fn (ti &Type) is_number() bool { return ti.is_int() || ti.is_float() } -pub fn (ti &TypeIdent) str() string { - mut muls := '' - for _ in 0 .. ti.nr_muls { - muls += '&' - } - // return '$muls$ti.name' - return '$muls$ti.idx' -} - pub fn (k Kind) str() string { k_str := match k { .unresolved{ @@ -142,10 +236,10 @@ pub fn (k Kind) str() string { 'byteptr' } // .const_{ - // 'const' + // 'const' // } // .enum_{ - // 'enum' + // 'enum' // } .struct_{ 'struct' @@ -217,38 +311,32 @@ pub fn (kinds []Kind) str() string { // pub struct Const { // pub: -// name string +// name string // } - // pub struct Enum { // pub: -// name string +// name string // } - pub struct Struct { pub mut: - fields []Field + fields []Field } pub struct Field { pub: - name string - ti TypeIdent + name string + ti Type // type_idx int } - // pub struct Int { // pub: -// bit_size u32 -// is_unsigned bool +// bit_size u32 +// is_unsigned bool // } - // pub struct Float { // pub: -// bit_size u32 +// bit_size u32 // } - - pub struct Array { pub: elem_type_kind Kind @@ -277,10 +365,32 @@ pub: pub struct MultiReturn { pub: name string - tis []TypeIdent + tis []Type } pub struct Variadic { pub: - ti TypeIdent + ti Type +} + +pub fn (t &Table) refresh_ti(ti Type) Type { + if ti.idx == 0 { + return ti + } + if ti.kind in [.placeholder, .unresolved] { + typ := t.types[ti.idx] + return { + ti | + kind:typ.kind, + name:typ.name + } + } + return ti +} + +pub fn (t &Table) get_type(idx int) Type { + if idx == 0 { + panic('get_type: idx 0') + } + return t.types[idx] } diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index c9a44e5b2c..a74433bbde 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -1,51 +1,37 @@ +// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. module table - -import ( - v.ast - v.types -) - +// import ( +// v.ast +// ) pub struct Table { // struct_fields map[string][]string pub mut: - types []Type + types []Type // type_idxs Hashmap - type_idxs map[string]int - local_vars []Var + type_idxs map[string]int + local_vars []Var // fns Hashmap - fns map[string]Fn - tmp_cnt int - imports []string + fns map[string]Fn + tmp_cnt int + imports []string } pub struct Fn { pub: - name string - args []Var - return_ti types.TypeIdent + name string + args []Var + return_type Type } pub struct Var { pub: name string is_mut bool - expr ast.Expr + // expr ast.Expr mut: - ti types.TypeIdent -} - -pub struct Type { -pub: - parent_idx int -mut: - info types.TypeInfo - kind types.Kind - name string - methods []Fn -} - -pub fn (t Type) str() string { - return t.name + typ Type } pub fn new_table() &Table { @@ -54,52 +40,8 @@ pub fn new_table() &Table { return t } -pub fn (t mut Table) register_builtin_types() { - // reserve index 0 so nothing can go there - // save index check, 0 will mean not found - t.register_type(Type{kind: .placeholder, name: 'reserved_0'}) - t.register_type(Type{kind: .void, name: 'void'}) - t.register_type(Type{kind: .voidptr, name: 'voidptr'}) - t.register_type(Type{kind: .charptr, name: 'charptr'}) - t.register_type(Type{kind: .byteptr, name: 'byteptr'}) - t.register_type(Type{kind: .i8, name: 'i8'}) - t.register_type(Type{kind: .i16, name: 'i16'}) - t.register_type(Type{kind: .int, name: 'int'}) - t.register_type(Type{kind: .i64, name: 'i64'}) - t.register_type(Type{kind: .u16, name: 'u16'}) - t.register_type(Type{kind: .u32, name: 'u32'}) - t.register_type(Type{kind: .u64, name: 'u64'}) - t.register_type(Type{kind: .f32, name: 'f32'}) - t.register_type(Type{kind: .f64, name: 'f64'}) - t.register_type(Type{kind: .string, name: 'string'}) - t.register_type(Type{kind: .char, name: 'char'}) - t.register_type(Type{kind: .byte, name: 'byte'}) - t.register_type(Type{kind: .bool, name: 'bool'}) -} - -pub fn (t &Table) refresh_ti(ti types.TypeIdent) types.TypeIdent { - if ti.idx == 0 { - return ti - } - if ti.kind in [.placeholder, .unresolved] { - typ := t.types[ti.idx] - return { ti| - kind: typ.kind, - name: typ.name - } - } - return ti -} - -pub fn (t &Table) get_type(idx int) Type { - if idx == 0 { - panic('get_type: idx 0') - } - return t.types[idx] -} - pub fn (t &Table) find_var_idx(name string) int { - for i,var in t.local_vars { + for i, var in t.local_vars { if var.name == name { return i } @@ -137,7 +79,7 @@ pub fn (t mut Table) clear_vars() { } pub fn (t mut Table) register_var(v Var) { - println('register_var: $v.name - $v.ti.name') + println('register_var: $v.name - $v.typ.name') t.local_vars << v /* mut new_var := { @@ -175,9 +117,9 @@ pub fn (t mut Table) register_fn(new_fn Fn) { t.fns[new_fn.name] = new_fn } -pub fn (t mut Table) register_method(ti &types.TypeIdent, new_fn Fn) bool { - idx := ti.idx - println('register method `$new_fn.name` type=$ti.name idx=$ti.idx') +pub fn (t mut Table) register_method(typ &Type, new_fn Fn) bool { + idx := typ.idx + println('register method `$new_fn.name` type=$typ.name idx=$typ.idx') mut methods := t.types[idx].methods methods << new_fn t.types[idx].methods = methods @@ -216,9 +158,9 @@ pub fn (t &Table) struct_has_field(s &Type, name string) bool { return false } -pub fn (t &Table) struct_find_field(s &Type, name string) ?types.Field { +pub fn (t &Table) struct_find_field(s &Type, name string) ?Field { println('struct_find_field($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx') - info := s.info as types.Struct + info := s.info as Struct for field in info.fields { if field.name == name { return field @@ -226,7 +168,7 @@ pub fn (t &Table) struct_find_field(s &Type, name string) ?types.Field { } if s.parent_idx != 0 { parent := t.types[s.parent_idx] - parent_info := s.info as types.Struct + parent_info := s.info as Struct println('got parent $parent.name') for field in parent_info.fields { if field.name == name { @@ -260,8 +202,9 @@ pub fn (t mut Table) register_type(typ Type) int { .placeholder { // override placeholder println('overriding type placeholder `$typ.name`') - t.types[existing_idx] = {typ| - methods: ex_type.methods + t.types[existing_idx] = { + typ | + methods:ex_type.methods } return existing_idx } @@ -271,7 +214,7 @@ pub fn (t mut Table) register_type(typ Type) int { } panic('cannot register type `$typ.name`, another type with this name exists') } - } + } } idx := t.types.len t.types << typ @@ -279,8 +222,8 @@ pub fn (t mut Table) register_type(typ Type) int { return idx } -pub fn (t mut Table) find_or_register_map(key_ti &types.TypeIdent, value_ti &types.TypeIdent) (int,string) { - name := 'map_${key_ti.name}_${value_ti.name}' +pub fn (t mut Table) find_or_register_map(key_typ &Type, value_typ &Type) (int,string) { + name := 'map_${key_typ.name}_${value_typ.name}' // existing existing_idx := t.type_idxs[name] if existing_idx > 0 { @@ -290,17 +233,17 @@ pub fn (t mut Table) find_or_register_map(key_ti &types.TypeIdent, value_ti &typ map_type := Type{ kind: .map name: name - info: types.Map{ - key_type_idx: key_ti.idx - value_type_idx: value_ti.idx + info: Map{ + key_type_idx: key_typ.idx + value_type_idx: value_typ.idx } } idx := t.register_type(map_type) return idx,name } -pub fn (t mut Table) find_or_register_array(elem_ti &types.TypeIdent, nr_dims int) (int,string) { - name := 'array_${elem_ti.name}' + if nr_dims > 1 { '_${nr_dims}d' } else { '' } +pub fn (t mut Table) find_or_register_array(elem_typ &Type, nr_dims int) (int,string) { + name := 'array_${elem_typ.name}' + if nr_dims > 1 { '_${nr_dims}d' } else { '' } // existing existing_idx := t.type_idxs[name] if existing_idx > 0 { @@ -312,9 +255,9 @@ pub fn (t mut Table) find_or_register_array(elem_ti &types.TypeIdent, nr_dims in parent_idx: parent_idx kind: .array name: name - info: types.Array{ - elem_type_idx: elem_ti.idx - elem_is_ptr: elem_ti.is_ptr() + info: Array{ + elem_type_idx: elem_typ.idx + elem_is_ptr: elem_typ.is_ptr() nr_dims: nr_dims } } @@ -322,8 +265,8 @@ pub fn (t mut Table) find_or_register_array(elem_ti &types.TypeIdent, nr_dims in return idx,name } -pub fn (t mut Table) find_or_register_array_fixed(elem_ti &types.TypeIdent, size int, nr_dims int) (int,string) { - name := 'array_fixed_${elem_ti.name}_${size}' + if nr_dims > 1 { '_${nr_dims}d' } else { '' } +pub fn (t mut Table) find_or_register_array_fixed(elem_typ &Type, size int, nr_dims int) (int,string) { + name := 'array_fixed_${elem_typ.name}_${size}' + if nr_dims > 1 { '_${nr_dims}d' } else { '' } // existing existing_idx := t.type_idxs[name] if existing_idx > 0 { @@ -333,9 +276,9 @@ pub fn (t mut Table) find_or_register_array_fixed(elem_ti &types.TypeIdent, size array_fixed_type := Type{ kind: .array_fixed name: name - info: types.ArrayFixed{ - elem_type_idx: elem_ti.idx - elem_is_ptr: elem_ti.is_ptr() + info: ArrayFixed{ + elem_type_idx: elem_typ.idx + elem_is_ptr: elem_typ.is_ptr() size: size nr_dims: nr_dims } @@ -344,10 +287,10 @@ pub fn (t mut Table) find_or_register_array_fixed(elem_ti &types.TypeIdent, size return idx,name } -pub fn (t mut Table) find_or_register_multi_return(mr_tis []types.TypeIdent) (int,string) { +pub fn (t mut Table) find_or_register_multi_return(mr_typs []Type) (int,string) { mut name := 'multi_return' - for mr_ti in mr_tis { - name += '_$mr_ti.name' + for mr_typ in mr_typs { + name += '_$mr_typ.name' } // existing existing_idx := t.type_idxs[name] @@ -358,16 +301,16 @@ pub fn (t mut Table) find_or_register_multi_return(mr_tis []types.TypeIdent) (in mr_type := Type{ kind: .multi_return name: name - info: types.MultiReturn{ - tis: mr_tis + info: MultiReturn{ + tis: mr_typs } } idx := t.register_type(mr_type) return idx,name } -pub fn (t mut Table) find_or_register_variadic(variadic_ti &types.TypeIdent) (int,string) { - name := 'variadic_$variadic_ti.name' +pub fn (t mut Table) find_or_register_variadic(variadic_typ &Type) (int,string) { + name := 'variadic_$variadic_typ.name' // existing existing_idx := t.type_idxs[name] if existing_idx > 0 { @@ -377,8 +320,8 @@ pub fn (t mut Table) find_or_register_variadic(variadic_ti &types.TypeIdent) (in variadic_type := Type{ kind: .variadic name: name - info: types.Variadic{ - ti: variadic_ti + info: Variadic{ + ti: variadic_typ } } idx := t.register_type(variadic_type) @@ -396,77 +339,76 @@ pub fn (t mut Table) add_placeholder_type(name string) int { } // [inline] -// pub fn (t &Table) update_ti(ti &types.TypeIdent) types.TypeIdent { -// if ti.kind == .unresolved { - -// } +// pub fn (t &Table) update_typ(ti &types.Type) types.Type { +// if typ.kind == .unresolved { // } - -pub fn (t &Table) check(got, expected &types.TypeIdent) bool { +// } +pub fn (t &Table) check(got, expected &Type) bool { println('check: $got.name, $expected.name') if expected.kind == .voidptr { return true } - //if expected.name == 'array' { - // return true - //} + // if expected.name == 'array' { + // return true + // } if got.idx != expected.idx { return false } return true } +/* [inline] -pub fn (t &Table) get_expr_ti(expr ast.Expr) types.TypeIdent { +pub fn (t &Table) get_expr_typ(expr ast.Expr) Type { match expr { - ast.ArrayInit{ - return it.ti + ast.ArrayInit { + return it.typ } - ast.IndexExpr{ - return t.get_expr_ti(it.left) + ast.IndexExpr { + return t.get_expr_typ(it.left) } ast.CallExpr { func := t.find_fn(it.name) or { - return types.void_ti + return void_typ } - return func.return_ti + return func.return_typ } ast.MethodCallExpr { - ti := t.get_expr_ti(it.expr) - func := t.find_method(ti.idx, it.name) or { - return types.void_ti + ti := t.get_expr_typ(it.expr) + func := t.find_method(typ.idx, it.name) or { + return void_type } - return func.return_ti + return func.return_typ } ast.Ident { if it.kind == .variable { info := it.info as ast.IdentVar - if info.ti.kind != .unresolved { + if info.typ.kind != .unresolved { return info.ti } - return t.get_expr_ti(info.expr) + return t.get_expr_typ(info.expr) } - return types.void_ti + return types.void_typ } ast.StructInit { return it.ti } ast.StringLiteral { - return types.string_ti + return types.string_typ } ast.IntegerLiteral { - return types.int_ti + return types.int_typ } ast.SelectorExpr { - ti := t.get_expr_ti(it.expr) - kind := t.types[ti.idx].kind - if ti.kind == .placeholder { - println(' ##### PH $ti.name') + ti := t.get_expr_typ(it.expr) + kind := t.types[typ.idx].kind + if typ.kind == .placeholder { + println(' ##### PH $typ.name') } if !(kind in [.placeholder, .struct_]) { - return types.void_ti + return types.void_typ } - struct_ := t.types[ti.idx] + struct_ := t.types[typ.idx] struct_info := struct_.info as types.Struct for field in struct_info.fields { if field.name == it.field { @@ -482,13 +424,14 @@ pub fn (t &Table) get_expr_ti(expr ast.Expr) types.TypeIdent { } } } - return types.void_ti + return types.void_typ } - ast.BinaryExpr { - return t.get_expr_ti(it.left) + ast.InfixExpr { + return t.get_expr_typ(it.left) } else { - return types.void_ti + return types.void_typ } } } +*/ diff --git a/vlib/v/token/position.v b/vlib/v/token/position.v index 378a688a68..3f7c497069 100644 --- a/vlib/v/token/position.v +++ b/vlib/v/token/position.v @@ -12,7 +12,8 @@ pub: [inline] pub fn (tok &Token) position() Position { return Position{ - line_nr: tok.line_nr + line_nr: tok.line_nr - 1 // pos: tok.pos + } } diff --git a/vlib/v/types/types_test.v b/vlib/v/types/types_test.v deleted file mode 100644 index 93a62492b4..0000000000 --- a/vlib/v/types/types_test.v +++ /dev/null @@ -1,5 +0,0 @@ -module types - -fn test_types() { - -}