mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
v2: simplify the type system; an initial version of the V interpreter
This commit is contained in:
parent
932392a7fd
commit
9f4661391d
@ -589,4 +589,4 @@ fn test_clear() {
|
||||
|
||||
arr.clear()
|
||||
assert arr.len == 0
|
||||
}
|
||||
}
|
||||
|
@ -441,4 +441,4 @@ pub fn (m map_string) str() string {
|
||||
}
|
||||
sb.writeln('}')
|
||||
return sb.str()
|
||||
}
|
||||
}
|
||||
|
@ -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')
|
||||
|
@ -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')
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -32,4 +32,4 @@ fn test_eventbus(){
|
||||
|
||||
fn on_test(sender voidptr, ev &EventData) {
|
||||
assert ev.data == "hello"
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
fn C.fonsDrawDebug(s &C.FONScontext, x f32, y f32)
|
||||
|
@ -77,4 +77,4 @@ pub struct C.FONStextIter {
|
||||
|
||||
pub struct C.FONSfont {}
|
||||
|
||||
pub struct C.FONScontext {}
|
||||
pub struct C.FONScontext {}
|
||||
|
@ -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.
|
||||
)
|
||||
)
|
||||
|
@ -301,4 +301,4 @@ pub enum Action {
|
||||
load
|
||||
dontcare
|
||||
_num
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
fn C.sg_query_pass_defaults(desc &C.sg_pass) C.sg_pass_desc
|
||||
|
@ -457,4 +457,4 @@ pub mut:
|
||||
// layer int
|
||||
// slice int
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -155,4 +155,4 @@ pub enum KeyCode {
|
||||
right_alt = 346
|
||||
right_super = 347
|
||||
menu = 348
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
fn C.sfons_flush(ctx &FONScontext)
|
||||
|
@ -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()
|
||||
fn C.sgl_draw()
|
||||
|
@ -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 */
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
104
vlib/v/eval/eval.v
Normal file
104
vlib/v/eval/eval.v
Normal file
@ -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{}
|
||||
}
|
@ -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')
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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{
|
||||
|
@ -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]
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
module types
|
||||
|
||||
fn test_types() {
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user