1
0
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:
Alexander Medvednikov
2020-01-22 21:34:38 +01:00
parent 932392a7fd
commit 9f4661391d
33 changed files with 847 additions and 517 deletions

View File

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

View File

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

View File

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

View File

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