mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
simplify and improve pratt
This commit is contained in:
parent
025efcb731
commit
b815878d60
@ -38,7 +38,7 @@ fn expr1() Expr {
|
||||
//return BinExpr{}
|
||||
}
|
||||
|
||||
fn expr2() Expr {
|
||||
fn expr() Expr {
|
||||
return BinExpr{}
|
||||
}
|
||||
|
||||
|
@ -8,11 +8,12 @@ import (
|
||||
v.types
|
||||
)
|
||||
|
||||
pub type Expr = BinaryExpr | UnaryExpr | IfExpr | StringLiteral | IntegerLiteral |
|
||||
FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr
|
||||
pub type Expr = BinaryExpr | UnaryExpr | IfExpr | StringLiteral | IntegerLiteral |
|
||||
FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr | AssignExpr | PrefixExpr
|
||||
|
||||
pub type Stmt = VarDecl | FnDecl | Return | Module | Import | ExprStmt | AssignStmt |
|
||||
pub type Stmt = VarDecl | FnDecl | Return | Module | Import | ExprStmt | AssignStmt |
|
||||
ForStmt | StructDecl
|
||||
// | IncDecStmt k
|
||||
// Stand-alone expression in a statement list.
|
||||
pub struct ExprStmt {
|
||||
pub:
|
||||
@ -71,8 +72,8 @@ pub:
|
||||
|
||||
pub struct StructInit {
|
||||
pub:
|
||||
ti types.TypeIdent
|
||||
// typ types.Type
|
||||
// typ types.TypeIdent
|
||||
ti types.TypeIdent
|
||||
fields []string
|
||||
exprs []Expr
|
||||
}
|
||||
@ -80,26 +81,23 @@ pub:
|
||||
// import statement
|
||||
pub struct Import {
|
||||
pub:
|
||||
mods []string
|
||||
mods map[string]string // alias -> module
|
||||
// expr Expr
|
||||
// imports map[string]string
|
||||
}
|
||||
|
||||
pub struct Arg {
|
||||
pub:
|
||||
ti types.TypeIdent
|
||||
// typ types.Type
|
||||
name string
|
||||
}
|
||||
|
||||
pub struct FnDecl {
|
||||
pub:
|
||||
name string
|
||||
stmts []Stmt
|
||||
ti types.TypeIdent
|
||||
// typ types.Type
|
||||
args []Arg
|
||||
is_pub bool
|
||||
name string
|
||||
stmts []Stmt
|
||||
ti types.TypeIdent
|
||||
args []Arg
|
||||
is_pub bool
|
||||
receiver Field
|
||||
}
|
||||
|
||||
@ -137,7 +135,6 @@ pub:
|
||||
name string
|
||||
expr Expr
|
||||
ti types.TypeIdent
|
||||
// typ types.Type
|
||||
}
|
||||
|
||||
pub struct File {
|
||||
@ -159,9 +156,9 @@ pub:
|
||||
// op BinaryOp
|
||||
op token.Kind
|
||||
left Expr
|
||||
// left_type Type
|
||||
// left_ti types.TypeIdent
|
||||
right Expr
|
||||
// right_type Type
|
||||
// right_ti types.TypeIdent
|
||||
}
|
||||
|
||||
pub struct UnaryExpr {
|
||||
@ -172,6 +169,18 @@ pub:
|
||||
left Expr
|
||||
}
|
||||
|
||||
pub struct PostfixExpr {
|
||||
pub:
|
||||
op token.Kind
|
||||
expr Expr
|
||||
}
|
||||
|
||||
pub struct PrefixExpr {
|
||||
pub:
|
||||
op token.Kind
|
||||
right Expr
|
||||
}
|
||||
|
||||
pub struct IfExpr {
|
||||
pub:
|
||||
tok_kind token.Kind
|
||||
@ -179,7 +188,6 @@ pub:
|
||||
stmts []Stmt
|
||||
else_stmts []Stmt
|
||||
ti types.TypeIdent
|
||||
// typ types.Type
|
||||
left Expr // `a` in `a := if ...`
|
||||
}
|
||||
|
||||
@ -202,11 +210,17 @@ pub:
|
||||
op token.Kind
|
||||
}
|
||||
|
||||
pub struct AssignExpr {
|
||||
pub:
|
||||
left Expr
|
||||
val Expr
|
||||
op token.Kind
|
||||
}
|
||||
|
||||
pub struct ArrayInit {
|
||||
pub:
|
||||
exprs []Expr
|
||||
ti types.TypeIdent
|
||||
// typ types.Type
|
||||
}
|
||||
|
||||
// string representaiton of expr
|
||||
|
@ -14,6 +14,7 @@ struct Gen {
|
||||
}
|
||||
|
||||
pub fn cgen(files []ast.File, table &table.Table) string {
|
||||
println('start cgen')
|
||||
mut g := Gen{
|
||||
out: strings.new_builder(100)
|
||||
definitions: strings.new_builder(100)
|
||||
@ -39,25 +40,32 @@ pub fn (g mut Gen) writeln(s string) {
|
||||
}
|
||||
|
||||
fn (g mut Gen) stmt(node ast.Stmt) {
|
||||
// println('cgen.stmt()')
|
||||
// g.writeln('//// stmt start')
|
||||
match node {
|
||||
ast.Import {
|
||||
|
||||
}
|
||||
/*
|
||||
ast.AssignStmt {
|
||||
g.expr(it.left)
|
||||
g.write(' $it.op.str() ')
|
||||
g.expr(it.right)
|
||||
g.writeln(';')
|
||||
}
|
||||
*/
|
||||
ast.FnDecl {
|
||||
is_main := it.name == 'main'
|
||||
if is_main {
|
||||
g.write('int ${it.name}(')
|
||||
}
|
||||
else {
|
||||
g.write('$it.ti.type_name ${it.name}(')
|
||||
g.definitions.write('$it.ti.type_name ${it.name}(')
|
||||
g.write('$it.ti.name ${it.name}(')
|
||||
g.definitions.write('$it.ti.name ${it.name}(')
|
||||
}
|
||||
for arg in it.args {
|
||||
g.write(arg.ti.type_name + ' ' + arg.name)
|
||||
g.definitions.write(arg.ti.type_name + ' ' + arg.name)
|
||||
g.write(arg.ti.name + ' ' + arg.name)
|
||||
g.definitions.write(arg.ti.name + ' ' + arg.name)
|
||||
}
|
||||
g.writeln(') { ')
|
||||
if !is_main {
|
||||
@ -77,7 +85,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||
g.writeln(';')
|
||||
}
|
||||
ast.VarDecl {
|
||||
g.write('$it.ti.type_name $it.name = ')
|
||||
g.write('$it.ti.name $it.name = ')
|
||||
g.expr(it.expr)
|
||||
g.writeln(';')
|
||||
}
|
||||
@ -97,7 +105,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||
ast.StructDecl {
|
||||
g.writeln('typedef struct {')
|
||||
for field in it.fields {
|
||||
g.writeln('\t$field.ti.type_name $field.name;')
|
||||
g.writeln('\t$field.ti.name $field.name;')
|
||||
}
|
||||
g.writeln('} $it.name;')
|
||||
}
|
||||
@ -120,12 +128,21 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||
fn (g mut Gen) expr(node ast.Expr) {
|
||||
// println('cgen expr()')
|
||||
match node {
|
||||
ast.AssignExpr {
|
||||
g.expr(it.left)
|
||||
g.write(' $it.op.str() ')
|
||||
g.expr(it.val)
|
||||
}
|
||||
ast.IntegerLiteral {
|
||||
g.write(it.val.str())
|
||||
}
|
||||
ast.FloatLiteral {
|
||||
g.write(it.val)
|
||||
}
|
||||
ast.PostfixExpr {
|
||||
g.expr(it.expr)
|
||||
g.write(it.op.str())
|
||||
}
|
||||
ast.UnaryExpr {
|
||||
// probably not :D
|
||||
if it.op in [.inc, .dec] {
|
||||
@ -140,6 +157,10 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||
ast.StringLiteral {
|
||||
g.write('tos3("$it.val")')
|
||||
}
|
||||
ast.PrefixExpr {
|
||||
g.write(it.op.str())
|
||||
g.expr(it.right)
|
||||
}
|
||||
ast.BinaryExpr {
|
||||
g.expr(it.left)
|
||||
if it.op == .dot {
|
||||
@ -153,7 +174,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||
}
|
||||
// `user := User{name: 'Bob'}`
|
||||
ast.StructInit {
|
||||
g.writeln('($it.ti.type_name){')
|
||||
g.writeln('($it.ti.name){')
|
||||
for i, field in it.fields {
|
||||
g.write('\t.$field = ')
|
||||
g.expr(it.exprs[i])
|
||||
@ -172,7 +193,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||
g.write(')')
|
||||
}
|
||||
ast.ArrayInit {
|
||||
g.writeln('new_array_from_c_array($it.exprs.len, $it.exprs.len, sizeof($it.ti.type_name), {\t')
|
||||
g.writeln('new_array_from_c_array($it.exprs.len, $it.exprs.len, sizeof($it.ti.name), {\t')
|
||||
for expr in it.exprs {
|
||||
g.expr(expr)
|
||||
g.write(', ')
|
||||
@ -199,16 +220,16 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||
// If expression? Assign the value to a temp var.
|
||||
// Previously ?: was used, but it's too unreliable.
|
||||
mut tmp := ''
|
||||
if it.ti.type_kind != ._void {
|
||||
if it.ti.kind != ._void {
|
||||
tmp = g.table.new_tmp_var()
|
||||
// g.writeln('$it.typ.name $tmp;')
|
||||
// g.writeln('$it.ti.name $tmp;')
|
||||
}
|
||||
g.write('if (')
|
||||
g.expr(it.cond)
|
||||
g.writeln(') {')
|
||||
for i, stmt in it.stmts {
|
||||
// Assign ret value
|
||||
if i == it.stmts.len - 1 && it.ti.type_kind != ._void {
|
||||
if i == it.stmts.len - 1 && it.ti.kind != ._void {
|
||||
// g.writeln('$tmp =')
|
||||
println(1)
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
nr_tests = 2
|
||||
nr_tests = 3
|
||||
)
|
||||
|
||||
fn test_c_files() {
|
||||
|
@ -40,9 +40,9 @@ fn (g mut JsGen) stmt(node ast.Stmt) {
|
||||
g.writeln(';')
|
||||
}
|
||||
ast.FnDecl {
|
||||
g.write('/** @return { $it.ti.type_name } **/\nfunction ${it.name}(')
|
||||
g.write('/** @return { $it.ti.name } **/\nfunction ${it.name}(')
|
||||
for arg in it.args {
|
||||
g.write(' /** @type { arg.ti.type_name } **/ $arg.name')
|
||||
g.write(' /** @type { arg.ti.name } **/ $arg.name')
|
||||
}
|
||||
g.writeln(') { ')
|
||||
for stmt in it.stmts {
|
||||
@ -56,7 +56,7 @@ fn (g mut JsGen) stmt(node ast.Stmt) {
|
||||
g.writeln(';')
|
||||
}
|
||||
ast.VarDecl {
|
||||
g.write('var /* $it.ti.type_name */ $it.name = ')
|
||||
g.write('var /* $it.ti.name */ $it.name = ')
|
||||
g.expr(it.expr)
|
||||
g.writeln(';')
|
||||
}
|
||||
@ -72,7 +72,7 @@ fn (g mut JsGen) stmt(node ast.Stmt) {
|
||||
ast.StructDecl {
|
||||
// g.writeln('typedef struct {')
|
||||
// for field in it.fields {
|
||||
// g.writeln('\t$field.ti.type_name $field.name;')
|
||||
// g.writeln('\t$field.ti.name $field.name;')
|
||||
// }
|
||||
g.writeln('var $it.name = function() {};')
|
||||
}
|
||||
@ -115,7 +115,7 @@ fn (g mut JsGen) expr(node ast.Expr) {
|
||||
}
|
||||
// `user := User{name: 'Bob'}`
|
||||
ast.StructInit {
|
||||
g.writeln('/*$it.ti.type_name*/{')
|
||||
g.writeln('/*$it.ti.name*/{')
|
||||
for i, field in it.fields {
|
||||
g.write('\t$field : ')
|
||||
g.expr(it.exprs[i])
|
||||
|
@ -10,9 +10,10 @@ typedef struct {
|
||||
int main() {
|
||||
int a = 10;
|
||||
a++;
|
||||
int c = -a;
|
||||
int negative = -a;
|
||||
a == 1;
|
||||
foo(3);
|
||||
int ak = 10;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -37,4 +38,8 @@ void myuser() {
|
||||
int boo = 2;
|
||||
int boo2 = boo + 1;
|
||||
bool b = age > 0;
|
||||
bool b2 = user.age > 0;
|
||||
}
|
||||
|
||||
void variadic(variadic_int a) {
|
||||
}
|
||||
|
@ -1,13 +1,19 @@
|
||||
import moda
|
||||
import modb as mb
|
||||
|
||||
struct User {
|
||||
age int
|
||||
}
|
||||
|
||||
// lol
|
||||
fn main() {
|
||||
a := 10
|
||||
a++
|
||||
c := -a
|
||||
negative := -a
|
||||
a == 1
|
||||
foo(3)
|
||||
ak := 10
|
||||
}
|
||||
/*
|
||||
user := User{}
|
||||
user.age = 10
|
||||
@ -16,7 +22,6 @@ fn main() {
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
fn foo(a int) {
|
||||
n := get_int2()
|
||||
@ -37,5 +42,8 @@ fn myuser() {
|
||||
boo := 2
|
||||
boo2 := boo+1
|
||||
b := age > 0
|
||||
//b2 := user.age > 0
|
||||
b2 := user.age > 0
|
||||
}
|
||||
|
||||
fn variadic(a ...int) {
|
||||
}
|
||||
|
13
vlib/v/gen/tests/3.c
Normal file
13
vlib/v/gen/tests/3.c
Normal file
@ -0,0 +1,13 @@
|
||||
typedef struct {
|
||||
int age;
|
||||
string name;
|
||||
} User;
|
||||
|
||||
int main() {
|
||||
User user = (User){
|
||||
};
|
||||
user.age = 10;
|
||||
user.age++;
|
||||
user.name = tos3("bob");
|
||||
return 0;
|
||||
}
|
11
vlib/v/gen/tests/3.vv
Normal file
11
vlib/v/gen/tests/3.vv
Normal file
@ -0,0 +1,11 @@
|
||||
struct User {
|
||||
age int
|
||||
name string
|
||||
}
|
||||
|
||||
fn main() {
|
||||
user := User{}
|
||||
user.age = 10
|
||||
user.age++
|
||||
user.name = 'bob'
|
||||
}
|
@ -337,7 +337,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||
g.writeln(';')
|
||||
}
|
||||
ast.VarDecl {
|
||||
g.write('$it.ti.type_name $it.name = ')
|
||||
g.write('$it.ti.name $it.name = ')
|
||||
g.expr(it.expr)
|
||||
g.writeln(';')
|
||||
}
|
||||
@ -354,7 +354,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||
ast.StructDecl {
|
||||
g.writeln('typedef struct {')
|
||||
for field in it.fields {
|
||||
g.writeln('\t$field.ti.type_name $field.name;')
|
||||
g.writeln('\t$field.ti.name $field.name;')
|
||||
}
|
||||
g.writeln('} $it.name;')
|
||||
}
|
||||
@ -400,7 +400,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||
}
|
||||
// `user := User{name: 'Bob'}`
|
||||
ast.StructInit {
|
||||
g.writeln('($it.ti.type_name){')
|
||||
g.writeln('($it.ti.name){')
|
||||
for i, field in it.fields {
|
||||
g.write('\t.$field = ')
|
||||
g.expr(it.exprs[i])
|
||||
@ -426,7 +426,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||
|
||||
}
|
||||
ast.ArrayInit {
|
||||
g.writeln('new_array_from_c_array($it.exprs.len, $it.exprs.len, sizeof($it.ti.type_name), {\t')
|
||||
g.writeln('new_array_from_c_array($it.exprs.len, $it.exprs.len, sizeof($it.ti.name), {\t')
|
||||
for expr in it.exprs {
|
||||
g.expr(expr)
|
||||
g.write(', ')
|
||||
|
162
vlib/v/parser/a_type.v
Normal file
162
vlib/v/parser/a_type.v
Normal file
@ -0,0 +1,162 @@
|
||||
module parser
|
||||
|
||||
// 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.
|
||||
import v.types
|
||||
|
||||
pub fn (p mut Parser) parse_array_ti(nr_muls int) types.TypeIdent {
|
||||
p.check(.lsbr)
|
||||
// fixed array
|
||||
if p.tok.kind == .number {
|
||||
size := p.tok.lit.int()
|
||||
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)
|
||||
}
|
||||
// array
|
||||
elem_ti := p.parse_ti()
|
||||
mut nr_dims := 1
|
||||
for p.tok.kind == .lsbr {
|
||||
p.check(.lsbr)
|
||||
p.next()
|
||||
nr_dims++
|
||||
}
|
||||
p.check(.rsbr)
|
||||
idx,name := p.table.find_or_register_array(&elem_ti, nr_dims)
|
||||
return types.new_ti(._array, name, idx, nr_muls)
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) parse_map_ti(nr_muls int) types.TypeIdent {
|
||||
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)
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) parse_multi_return_ti() types.TypeIdent {
|
||||
p.check(.lpar)
|
||||
mut mr_tis := []&types.TypeIdent
|
||||
for {
|
||||
mr_ti := p.parse_ti()
|
||||
mr_tis << &mr_ti
|
||||
if p.tok.kind == .comma {
|
||||
p.check(.comma)
|
||||
}
|
||||
else {
|
||||
break
|
||||
}
|
||||
}
|
||||
p.check(.rpar)
|
||||
idx,name := p.table.find_or_register_multi_return(mr_tis)
|
||||
return types.new_ti(._multi_return, name, idx, 0)
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) parse_variadic_ti() types.TypeIdent {
|
||||
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)
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) parse_ti() types.TypeIdent {
|
||||
mut nr_muls := 0
|
||||
for p.tok.kind == .amp {
|
||||
p.check(.amp)
|
||||
nr_muls++
|
||||
}
|
||||
name := p.tok.lit
|
||||
match p.tok.kind {
|
||||
// array
|
||||
.lsbr {
|
||||
return p.parse_array_ti(nr_muls)
|
||||
}
|
||||
// multiple return
|
||||
.lpar {
|
||||
if nr_muls > 0 {
|
||||
p.error('parse_ti: unexpected `&` before multiple returns')
|
||||
}
|
||||
return p.parse_multi_return_ti()
|
||||
}
|
||||
// variadic
|
||||
.ellipsis {
|
||||
if nr_muls > 0 {
|
||||
p.error('parse_ti: unexpected `&` before variadic')
|
||||
}
|
||||
return p.parse_variadic_ti()
|
||||
}
|
||||
else {
|
||||
defer {
|
||||
p.next()
|
||||
}
|
||||
match name {
|
||||
// map
|
||||
'map' {
|
||||
return p.parse_map_ti(nr_muls)
|
||||
}
|
||||
'voidptr' {
|
||||
return types.new_base_ti(._voidptr, nr_muls)
|
||||
}
|
||||
'byteptr' {
|
||||
return types.new_base_ti(._byteptr, nr_muls)
|
||||
}
|
||||
'charptr' {
|
||||
return types.new_base_ti(._charptr, nr_muls)
|
||||
}
|
||||
'i8' {
|
||||
return types.new_base_ti(._i8, nr_muls)
|
||||
}
|
||||
'i16' {
|
||||
return types.new_base_ti(._i16, nr_muls)
|
||||
}
|
||||
'int' {
|
||||
return types.new_base_ti(._int, nr_muls)
|
||||
}
|
||||
'i64' {
|
||||
return types.new_base_ti(._i64, nr_muls)
|
||||
}
|
||||
'byte' {
|
||||
return types.new_base_ti(._byte, nr_muls)
|
||||
}
|
||||
'u16' {
|
||||
return types.new_base_ti(._u16, nr_muls)
|
||||
}
|
||||
'u32' {
|
||||
return types.new_base_ti(._u32, nr_muls)
|
||||
}
|
||||
'u64' {
|
||||
return types.new_base_ti(._u64, nr_muls)
|
||||
}
|
||||
'f32' {
|
||||
return types.new_base_ti(._f32, nr_muls)
|
||||
}
|
||||
'f64' {
|
||||
return types.new_base_ti(._f64, nr_muls)
|
||||
}
|
||||
'string' {
|
||||
return types.new_base_ti(._string, nr_muls)
|
||||
}
|
||||
'char' {
|
||||
return types.new_base_ti(._char, nr_muls)
|
||||
}
|
||||
'bool' {
|
||||
return types.new_base_ti(._bool, nr_muls)
|
||||
}
|
||||
// struct / enum / placeholder
|
||||
else {
|
||||
// struct / enum
|
||||
mut idx := p.table.find_type_idx(name)
|
||||
// add placeholder
|
||||
if idx == 0 {
|
||||
idx = p.table.add_placeholder_type(name)
|
||||
}
|
||||
return types.new_ti(._placeholder, name, idx, nr_muls)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -15,14 +15,15 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,types.TypeIdent) {
|
||||
fn_name := p.check_name()
|
||||
p.check(.lpar)
|
||||
mut is_unknown := false
|
||||
is_unknown = false
|
||||
mut args := []ast.Expr
|
||||
mut return_ti := types.new_base_ti(._void, 0)
|
||||
mut return_ti := types.void_ti
|
||||
if f := p.table.find_fn(fn_name) {
|
||||
return_ti = f.return_ti
|
||||
for i, arg in f.args {
|
||||
e,ti := p.expr(0)
|
||||
if !types.check(arg.ti, ti) {
|
||||
p.error('cannot use type `$ti.type_name` as type `$arg.ti.type_name` in argument to `$fn_name`')
|
||||
if !types.check(&arg.ti, &ti) {
|
||||
p.error('cannot use type `$ti.name` as type `$arg.ti.name` in argument to `$fn_name`')
|
||||
}
|
||||
args << e
|
||||
if i < f.args.len - 1 {
|
||||
@ -49,7 +50,7 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,types.TypeIdent) {
|
||||
args: args
|
||||
is_unknown: is_unknown
|
||||
tok: tok
|
||||
// typ: return_type
|
||||
// typ: return_ti
|
||||
|
||||
}
|
||||
if is_unknown {
|
||||
@ -67,7 +68,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||
p.check(.key_fn)
|
||||
// Receiver?
|
||||
mut rec_name := ''
|
||||
mut rec_ti := types.new_base_ti(._void, 0)
|
||||
mut rec_ti := types.void_ti
|
||||
if p.tok.kind == .lpar {
|
||||
p.next()
|
||||
rec_name = p.check_name()
|
||||
@ -113,8 +114,8 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||
}
|
||||
p.check(.rpar)
|
||||
// Return type
|
||||
mut ti := types.new_base_ti(._void, 0)
|
||||
if p.tok.kind in [.amp, .name] {
|
||||
mut ti := types.void_ti
|
||||
if p.tok.kind == .name {
|
||||
ti = p.parse_ti()
|
||||
p.return_ti = ti
|
||||
}
|
||||
@ -145,7 +146,7 @@ pub fn (p &Parser) check_fn_calls() {
|
||||
return
|
||||
}
|
||||
println(f.name)
|
||||
// println(f.return_type.name)
|
||||
// println(f.return_ti.name)
|
||||
// println('IN AST typ=' + call.typ.name)
|
||||
}
|
||||
}
|
||||
|
@ -13,16 +13,24 @@ import (
|
||||
os
|
||||
)
|
||||
|
||||
type PrefixParseFn fn()ast.Expr
|
||||
|
||||
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_ti types.TypeIdent
|
||||
is_c bool
|
||||
//
|
||||
prefix_parse_fns []PrefixParseFn
|
||||
}
|
||||
|
||||
pub fn parse_stmt(text string, table &table.Table) ast.Stmt {
|
||||
@ -31,135 +39,13 @@ pub fn parse_stmt(text string, table &table.Table) ast.Stmt {
|
||||
scanner: s
|
||||
table: table
|
||||
}
|
||||
p.init_parse_fns()
|
||||
p.read_first_token()
|
||||
return p.stmt()
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) parse_ti() types.TypeIdent {
|
||||
defer {
|
||||
p.next()
|
||||
}
|
||||
mut nr_muls := 0
|
||||
if p.tok.kind == .amp {
|
||||
p.check(.amp)
|
||||
nr_muls = 1
|
||||
}
|
||||
name := p.tok.lit
|
||||
if nr_muls > 0 {
|
||||
println('## POINTER: $name')
|
||||
}
|
||||
match name {
|
||||
'voidptr' {
|
||||
return types.new_base_ti(._voidptr, nr_muls)
|
||||
}
|
||||
'byteptr' {
|
||||
return types.new_base_ti(._byteptr, nr_muls)
|
||||
}
|
||||
'charptr' {
|
||||
return types.new_base_ti(._charptr, nr_muls)
|
||||
}
|
||||
'164' {
|
||||
return types.new_base_ti(._i16, nr_muls)
|
||||
}
|
||||
'int' {
|
||||
return types.new_base_ti(._int, nr_muls)
|
||||
}
|
||||
'i64' {
|
||||
return types.new_base_ti(._i64, nr_muls)
|
||||
}
|
||||
'byte' {
|
||||
return types.new_base_ti(._byte, nr_muls)
|
||||
}
|
||||
'u16' {
|
||||
return types.new_base_ti(._u16, nr_muls)
|
||||
}
|
||||
'u32' {
|
||||
return types.new_base_ti(._u32, nr_muls)
|
||||
}
|
||||
'u64' {
|
||||
return types.new_base_ti(._u64, nr_muls)
|
||||
}
|
||||
'f32' {
|
||||
return types.new_base_ti(._f32, nr_muls)
|
||||
}
|
||||
'f64' {
|
||||
return types.new_base_ti(._f64, nr_muls)
|
||||
}
|
||||
'string' {
|
||||
return types.new_base_ti(._string, nr_muls)
|
||||
}
|
||||
'char' {
|
||||
return types.new_base_ti(._char, nr_muls)
|
||||
}
|
||||
'bool' {
|
||||
return types.new_base_ti(._bool, nr_muls)
|
||||
}
|
||||
else {
|
||||
// array
|
||||
if p.tok.kind == .lsbr {
|
||||
p.check(.lsbr)
|
||||
// fixed array
|
||||
if p.tok.kind == .number {
|
||||
fixed_size := p.tok.lit.int()
|
||||
p.check(.rsbr)
|
||||
elem_ti := p.parse_ti()
|
||||
array_fixed_type := types.ArrayFixed{
|
||||
name: 'array_fixed_$elem_ti.type_name'
|
||||
size: fixed_size
|
||||
elem_type_idx: elem_ti.type_idx
|
||||
elem_is_ptr: elem_ti.is_ptr()
|
||||
}
|
||||
idx := p.table.find_or_register_array_fixed(array_fixed_type)
|
||||
return types.new_ti(._array_fixed, array_fixed_type.name, idx, nr_muls)
|
||||
}
|
||||
p.check(.rsbr)
|
||||
// array
|
||||
elem_ti := p.parse_ti()
|
||||
array_type := types.Array{
|
||||
name: 'array_$elem_ti.type_name'
|
||||
elem_type_idx: elem_ti.type_idx
|
||||
elem_is_ptr: elem_ti.is_ptr()
|
||||
}
|
||||
idx := p.table.find_or_register_array(array_type)
|
||||
return types.new_ti(._array, array_type.name, idx, nr_muls)
|
||||
}
|
||||
// map
|
||||
else if name == 'map' {
|
||||
p.next()
|
||||
p.check(.lsbr)
|
||||
key_ti := p.parse_ti()
|
||||
p.check(.rsbr)
|
||||
value_ti := p.parse_ti()
|
||||
map_type := types.Map{
|
||||
name: 'map_${key_ti.type_name}_${value_ti.type_name}'
|
||||
key_type_idx: key_ti.type_idx,
|
||||
value_type_idx: value_ti.type_idx
|
||||
}
|
||||
idx := p.table.find_or_register_map(map_type)
|
||||
return types.new_ti(._map, map_type.name, idx, nr_muls)
|
||||
} else {
|
||||
// struct / enum
|
||||
mut idx := p.table.find_type_idx(name)
|
||||
// add placeholder
|
||||
if idx == 0 {
|
||||
idx = p.table.add_placeholder_type(name)
|
||||
}
|
||||
return types.new_ti(._placeholder, name, idx, nr_muls)
|
||||
}
|
||||
|
||||
// typ := p.table.find_type(p.tok.lit) or {
|
||||
// // typ := p.table.types[p.tok.lit]
|
||||
// // if isnil(typ.name.str) || typ.name == '' {
|
||||
// p.error('undefined type `$p.tok.lit`')
|
||||
// exit(0)
|
||||
// }
|
||||
// println('RET Typ $typ.name')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_file(path string, table &table.Table) ast.File {
|
||||
println('parse file "$path"')
|
||||
println('parse_file("$path")')
|
||||
text := os.read_file(path) or {
|
||||
panic(err)
|
||||
}
|
||||
@ -173,12 +59,11 @@ pub fn parse_file(path string, table &table.Table) ast.File {
|
||||
for {
|
||||
// res := s.scan()
|
||||
if p.tok.kind == .eof {
|
||||
println('EOF, breaking')
|
||||
break
|
||||
}
|
||||
// println('expr at ' + p.tok.str())
|
||||
s := p.stmt()
|
||||
// println(s)
|
||||
stmts << s // p.stmt()
|
||||
// println('stmt at ' + p.tok.str())
|
||||
stmts << p.top_stmt()
|
||||
}
|
||||
p.check_fn_calls()
|
||||
// println('nr stmts = $stmts.len')
|
||||
@ -196,6 +81,11 @@ pub fn parse_files(paths []string, table &table.Table) []ast.File {
|
||||
return files
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) init_parse_fns() {
|
||||
p.prefix_parse_fns = make(100, 100, sizeof(PrefixParseFn))
|
||||
// p.prefix_parse_fns[token.Kind.name] = parse_name
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) read_first_token() {
|
||||
// need to call next() twice to get peek token and current token
|
||||
p.next()
|
||||
@ -205,13 +95,14 @@ pub fn (p mut Parser) read_first_token() {
|
||||
pub fn (p mut Parser) parse_block() []ast.Stmt {
|
||||
p.check(.lcbr)
|
||||
mut stmts := []ast.Stmt
|
||||
for {
|
||||
// res := s.scan()
|
||||
if p.tok.kind in [.eof, .rcbr] {
|
||||
break
|
||||
if p.tok.kind != .rcbr {
|
||||
for {
|
||||
stmts << p.stmt()
|
||||
// p.warn('after stmt(): tok=$p.tok.str()')
|
||||
if p.tok.kind in [.eof, .rcbr] {
|
||||
break
|
||||
}
|
||||
}
|
||||
// println('expr at ' + p.tok.str())
|
||||
stmts << p.stmt()
|
||||
}
|
||||
p.check(.rcbr)
|
||||
// println('nr exprs in block = $exprs.len')
|
||||
@ -238,17 +129,7 @@ fn (p mut Parser) check_name() string {
|
||||
return name
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) stmt() ast.Stmt {
|
||||
// println('stmt at ' + p.tok.str())
|
||||
// `x := ...`
|
||||
if p.tok.kind == .name {
|
||||
if p.peek_tok.kind == .decl_assign {
|
||||
return p.var_decl()
|
||||
}
|
||||
else if p.peek_tok.is_assign() {
|
||||
return p.assign_stmt()
|
||||
}
|
||||
}
|
||||
pub fn (p mut Parser) top_stmt() ast.Stmt {
|
||||
match p.tok.kind {
|
||||
.key_module {
|
||||
return p.module_decl()
|
||||
@ -285,16 +166,30 @@ pub fn (p mut Parser) stmt() ast.Stmt {
|
||||
.key_struct {
|
||||
return p.struct_decl()
|
||||
}
|
||||
.key_return {
|
||||
return p.return_stmt()
|
||||
else {
|
||||
p.error('bad top level statement')
|
||||
return ast.Module{} // silence C warning
|
||||
// exit(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) stmt() ast.Stmt {
|
||||
match p.tok.kind {
|
||||
.key_mut {
|
||||
return p.var_decl()
|
||||
}
|
||||
.key_for {
|
||||
return p.for_statement()
|
||||
}
|
||||
.key_return {
|
||||
return p.return_stmt()
|
||||
}
|
||||
else {
|
||||
// `x := ...`
|
||||
if p.tok.kind == .name && p.peek_tok.kind == .decl_assign {
|
||||
return p.var_decl()
|
||||
}
|
||||
expr,ti := p.expr(0)
|
||||
return ast.ExprStmt{
|
||||
expr: expr
|
||||
@ -304,11 +199,24 @@ 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)
|
||||
node := ast.AssignExpr{
|
||||
left: left
|
||||
op: op
|
||||
val: val
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn (p mut Parser) assign_stmt() ast.AssignStmt {
|
||||
name := p.tok.lit
|
||||
// println('looking for $name')
|
||||
var := p.table.find_var(name) or {
|
||||
p.error('unknown variable `$name`')
|
||||
p.error('assign unknown variable `$name`')
|
||||
exit(1)
|
||||
}
|
||||
if !var.is_mut {
|
||||
@ -328,6 +236,8 @@ pub fn (p mut Parser) assign_stmt() ast.AssignStmt {
|
||||
op: op
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
pub fn (p &Parser) error(s string) {
|
||||
println(term.bold(term.red('$p.file_name:$p.tok.line_nr: $s')))
|
||||
@ -343,138 +253,137 @@ pub fn (p &Parser) warn(s string) {
|
||||
println(term.blue('$p.file_name:$p.tok.line_nr: $s'))
|
||||
}
|
||||
|
||||
// Implementation of Pratt Precedence
|
||||
pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.TypeIdent) {
|
||||
// println('expr at ' + p.tok.str())
|
||||
// null denotation (prefix)
|
||||
pub fn (p mut Parser) name_expr() (ast.Expr,types.TypeIdent) {
|
||||
mut node := ast.Expr{}
|
||||
// mut typ := types.void_type
|
||||
mut ti := types.new_base_ti(._void, 0)
|
||||
mut ti := types.void_ti
|
||||
// fn call
|
||||
if p.peek_tok.kind == .lpar {
|
||||
x,ti2 := p.call_expr() // TODO `node,typ :=` should work
|
||||
node = x
|
||||
ti = ti2
|
||||
}
|
||||
// struct init
|
||||
else if p.peek_tok.kind == .lcbr {
|
||||
ti = p.parse_ti()
|
||||
// println('sturct init ti=$ti.name')
|
||||
p.check(.lcbr)
|
||||
mut field_names := []string
|
||||
mut exprs := []ast.Expr
|
||||
for p.tok.kind != .rcbr {
|
||||
field_name := p.check_name()
|
||||
field_names << field_name
|
||||
p.check(.colon)
|
||||
// expr,field_type := p.expr(0)
|
||||
expr,_ := p.expr(0)
|
||||
// if !types.check( ,field_type
|
||||
exprs << expr
|
||||
}
|
||||
node = ast.StructInit{
|
||||
ti: ti
|
||||
exprs: exprs
|
||||
fields: field_names
|
||||
}
|
||||
p.check(.rcbr)
|
||||
}
|
||||
else {
|
||||
// p.warn('name ')
|
||||
// left := p.parse_ident()
|
||||
node = ast.Ident{
|
||||
name: p.tok.lit
|
||||
}
|
||||
var := p.table.find_var(p.tok.lit) or {
|
||||
p.error('name expr unknown variable `$p.tok.lit`')
|
||||
exit(0)
|
||||
}
|
||||
ti = var.ti
|
||||
p.next()
|
||||
}
|
||||
return node,ti
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) expr(precedence int) (ast.Expr,types.TypeIdent) {
|
||||
mut ti := types.void_ti
|
||||
mut node := ast.Expr{}
|
||||
// Prefix
|
||||
match p.tok.kind {
|
||||
.name {
|
||||
/*
|
||||
sym := p.table.find_symbol(p.tok.lit)
|
||||
if sym.cat == .function {
|
||||
return
|
||||
}
|
||||
*/
|
||||
if p.tok.lit == 'C' {
|
||||
p.is_c = true
|
||||
println('is c')
|
||||
p.next()
|
||||
p.check(.dot)
|
||||
}
|
||||
// fn call
|
||||
if p.peek_tok.kind == .lpar {
|
||||
x,ti2 := p.call_expr() // TODO `node,typ :=` should work
|
||||
node = x
|
||||
ti = ti2
|
||||
}
|
||||
// struct init
|
||||
else if p.peek_tok.kind == .lcbr {
|
||||
ti = p.parse_ti()
|
||||
// println('sturct init typ=$typ.name')
|
||||
p.check(.lcbr)
|
||||
mut field_names := []string
|
||||
mut exprs := []ast.Expr
|
||||
for p.tok.kind != .rcbr {
|
||||
field_name := p.check_name()
|
||||
field_names << field_name
|
||||
p.check(.colon)
|
||||
// expr,field_type := p.expr(0)
|
||||
expr,_ := p.expr(0)
|
||||
// if !types.check( ,field_type
|
||||
exprs << expr
|
||||
}
|
||||
node = ast.StructInit{
|
||||
ti: ti
|
||||
exprs: exprs
|
||||
fields: field_names
|
||||
}
|
||||
p.check(.rcbr)
|
||||
}
|
||||
else {
|
||||
// name expr
|
||||
node = ast.Ident{
|
||||
name: p.tok.lit
|
||||
}
|
||||
var := p.table.find_var(p.tok.lit) or {
|
||||
p.error('unknown variable `$p.tok.lit`')
|
||||
exit(0)
|
||||
}
|
||||
ti = var.ti
|
||||
// ///typ = types.int_type
|
||||
p.next()
|
||||
}
|
||||
node,ti = p.name_expr()
|
||||
}
|
||||
.lsbr {
|
||||
node,ti = p.array_init()
|
||||
.str {
|
||||
node,ti = p.parse_string_literal()
|
||||
}
|
||||
// -1, -a etc
|
||||
.minus {
|
||||
node,ti = p.prefix_expr()
|
||||
}
|
||||
.key_true, .key_false {
|
||||
node = ast.BoolLiteral{
|
||||
val: p.tok.kind == .key_true
|
||||
}
|
||||
ti = types.new_base_ti(._bool, 0)
|
||||
ti = types.bool_ti
|
||||
p.next()
|
||||
}
|
||||
.str {
|
||||
node,ti = p.parse_string_literal()
|
||||
}
|
||||
.number {
|
||||
node,ti = p.parse_number_literal()
|
||||
}
|
||||
.key_if {
|
||||
node,ti = p.if_expr()
|
||||
}
|
||||
.lpar {
|
||||
p.check(.lpar)
|
||||
p.next()
|
||||
node,ti = p.expr(token.lowest_prec)
|
||||
node,ti = p.expr(0)
|
||||
p.check(.rpar)
|
||||
}
|
||||
.key_if {
|
||||
node,ti = p.if_expr()
|
||||
}
|
||||
.lsbr {
|
||||
node,ti = p.array_init()
|
||||
}
|
||||
else {
|
||||
if p.tok.is_unary() {
|
||||
pt := p.tok
|
||||
p.next()
|
||||
expr,ti2 := p.expr(token.lowest_prec)
|
||||
node = ast.UnaryExpr{
|
||||
left: expr
|
||||
op: pt.kind
|
||||
}
|
||||
ti = ti2
|
||||
}
|
||||
else {
|
||||
p.error('expr(): unknown token ' + p.tok.str() + ' kind=$p.tok.kind')
|
||||
}
|
||||
p.error('expr(): bad token `$p.tok.str()`')
|
||||
}
|
||||
}
|
||||
// left binding power
|
||||
for rbp < p.tok.precedence() {
|
||||
prev_tok := p.tok
|
||||
p.next()
|
||||
// mut t2 := types.Type{}
|
||||
mut ti2 := types.new_base_ti(._void, 0)
|
||||
// left denotation (infix / postfix)
|
||||
if prev_tok.is_right_assoc() && !p.tok.kind in [.plus, .minus] && // think of better way to handle this
|
||||
!p.peek_tok.kind in [.number, .name] {
|
||||
// supposed to be only unary, additive handled in left asssoc
|
||||
mut expr := ast.Expr{}
|
||||
expr,ti2 = p.expr(prev_tok.precedence() - 1)
|
||||
node = ast.BinaryExpr{
|
||||
left: node
|
||||
op: prev_tok.kind
|
||||
right: expr
|
||||
}
|
||||
// println(t2.name + 'OOO')
|
||||
if !types.check(&ti, &ti2) {
|
||||
println('tok: $prev_tok.str()')
|
||||
p.error('cannot convert `$ti2.type_name` to `$ti.type_name`')
|
||||
}
|
||||
// Infix
|
||||
for precedence < p.tok.precedence() {
|
||||
if p.tok.kind.is_assign() {
|
||||
node = p.assign_expr(node)
|
||||
}
|
||||
else if prev_tok.is_left_assoc() {
|
||||
// postfix `.`
|
||||
if prev_tok.kind == .dot {
|
||||
p.warn('dot prev_tok = $prev_tok.str() typ=$ti.type_name')
|
||||
else if p.tok.kind == .dot {
|
||||
node,ti = p.dot_expr(node)
|
||||
}
|
||||
else if p.tok.kind.is_infix() {
|
||||
node,ti = p.infix_expr(node)
|
||||
}
|
||||
else if p.tok.kind in [.inc, .dec] {
|
||||
node = ast.PostfixExpr{
|
||||
op: p.tok.kind
|
||||
expr: node
|
||||
}
|
||||
p.next()
|
||||
return node,ti
|
||||
}
|
||||
else {
|
||||
return node,ti
|
||||
}
|
||||
}
|
||||
return node,ti
|
||||
}
|
||||
|
||||
fn (p mut Parser) prefix_expr() (ast.Expr,types.TypeIdent) {
|
||||
op := p.tok.kind
|
||||
p.next()
|
||||
right,ti := p.expr(1)
|
||||
mut expr := ast.Expr{}
|
||||
expr = ast.PrefixExpr{
|
||||
op: op
|
||||
right: right
|
||||
}
|
||||
return expr,ti
|
||||
}
|
||||
|
||||
fn (p mut Parser) dot_expr(left ast.Expr) (ast.Expr,types.TypeIdent) {
|
||||
p.next()
|
||||
field_name := p.check_name()
|
||||
/*
|
||||
// p.next()
|
||||
field := p.check_name()
|
||||
if !ti.type_kind in [._placeholder, ._struct] {
|
||||
@ -491,41 +400,36 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.TypeIdent) {
|
||||
if !ok {
|
||||
p.error('unknown field `${typ.name}.$field`')
|
||||
}
|
||||
node = ast.SelectorExpr{
|
||||
expr: node
|
||||
field: field
|
||||
}
|
||||
// return node,typ
|
||||
}
|
||||
// postfix (`++` | `--`)
|
||||
else if prev_tok.kind in [.inc, .dec] {
|
||||
node = ast.UnaryExpr{
|
||||
left: node
|
||||
op: prev_tok.kind
|
||||
}
|
||||
}
|
||||
else {
|
||||
mut expr := ast.Expr{}
|
||||
expr,ti2 = p.expr(prev_tok.precedence() - 1)
|
||||
if prev_tok.is_relational() {
|
||||
// typ = types.bool_type
|
||||
ti = types.new_base_ti(._bool, 0)
|
||||
}
|
||||
else {
|
||||
ti = ti2
|
||||
}
|
||||
// println(ti2.type_name + '222')
|
||||
node = ast.BinaryExpr{
|
||||
left: node
|
||||
op: prev_tok.kind
|
||||
right: expr
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
mut node := ast.Expr{}
|
||||
node = ast.SelectorExpr{
|
||||
expr: left
|
||||
field: field_name
|
||||
}
|
||||
return node,ti
|
||||
return node,types.int_ti
|
||||
}
|
||||
|
||||
fn (p mut Parser) infix_expr(left ast.Expr) (ast.Expr,types.TypeIdent) {
|
||||
op := p.tok.kind
|
||||
// mut typ := p.
|
||||
// println('infix op=$op.str()')
|
||||
precedence := p.tok.precedence()
|
||||
p.next()
|
||||
right,mut ti := p.expr(precedence)
|
||||
if op.is_relational() {
|
||||
ti = types.bool_ti
|
||||
}
|
||||
mut expr := ast.Expr{}
|
||||
expr = ast.BinaryExpr{
|
||||
op: op
|
||||
left: left
|
||||
right: right
|
||||
}
|
||||
return expr,ti
|
||||
}
|
||||
|
||||
// Implementation of Pratt Precedence
|
||||
[inline]
|
||||
fn (p &Parser) is_addative() bool {
|
||||
return p.tok.kind in [.plus, .minus] && p.peek_tok.kind in [.number, .name]
|
||||
@ -552,8 +456,7 @@ fn (p mut Parser) for_statement() ast.ForStmt {
|
||||
}
|
||||
// `for cond {`
|
||||
cond,ti := p.expr(0)
|
||||
// if !types.check(types.bool_type, ti) {
|
||||
if ti.type_kind != ._bool {
|
||||
if !types.check(types.bool_ti, ti) {
|
||||
p.error('non-bool used as for condition')
|
||||
}
|
||||
stmts := p.parse_block()
|
||||
@ -566,27 +469,25 @@ fn (p mut Parser) for_statement() ast.ForStmt {
|
||||
fn (p mut Parser) if_expr() (ast.Expr,types.TypeIdent) {
|
||||
mut node := ast.Expr{}
|
||||
p.check(.key_if)
|
||||
cond,cond_type := p.expr(0)
|
||||
// if !types.check(types.bool_type, cond_type) {
|
||||
if cond_type.type_kind != ._bool {
|
||||
cond,cond_ti := p.expr(0)
|
||||
// if !types.check(types.bool_ti, cond_ti) {
|
||||
if cond_ti.kind != ._bool {
|
||||
p.error('non-bool used as if condition')
|
||||
}
|
||||
stmts := p.parse_block()
|
||||
mut else_stmts := []ast.Stmt
|
||||
if p.tok.kind == .key_else {
|
||||
// println('GOT ELSE')
|
||||
p.check(.key_else)
|
||||
else_stmts = p.parse_block()
|
||||
}
|
||||
// mut typ := types.void_type
|
||||
mut ti := types.new_base_ti(._void, 0)
|
||||
mut ti := types.void_ti
|
||||
// mut left := ast.Expr{}
|
||||
// If the last statement is an expression, return its type
|
||||
match stmts[stmts.len - 1] {
|
||||
ast.ExprStmt {
|
||||
p.warn('if expr ret $it.ti.type_name')
|
||||
p.warn('if expr ret $it.ti.name')
|
||||
ti = it.ti
|
||||
// return node,it.typ
|
||||
// return node,it.ti
|
||||
// left =
|
||||
}
|
||||
else {}
|
||||
@ -608,14 +509,12 @@ fn (p mut Parser) parse_string_literal() (ast.Expr,types.TypeIdent) {
|
||||
val: p.tok.lit
|
||||
}
|
||||
p.next()
|
||||
// return node,types.string_type
|
||||
return node, types.new_base_ti(._string, 0)
|
||||
return node,types.string_ti
|
||||
}
|
||||
|
||||
fn (p mut Parser) array_init() (ast.Expr,types.TypeIdent) {
|
||||
p.check(.lsbr)
|
||||
// mut val_type := types.void_type
|
||||
mut val_ti := types.new_base_ti(._void, 0)
|
||||
mut val_ti := types.void_ti
|
||||
mut exprs := []ast.Expr
|
||||
mut i := 0
|
||||
for p.tok.kind != .rsbr {
|
||||
@ -625,7 +524,7 @@ fn (p mut Parser) array_init() (ast.Expr,types.TypeIdent) {
|
||||
val_ti = ti
|
||||
}
|
||||
else if !types.check(val_ti, ti) {
|
||||
p.error('expected array element with type `$val_ti.type_name`')
|
||||
p.error('expected array element with type `$val_ti.name`')
|
||||
}
|
||||
exprs << expr
|
||||
i++
|
||||
@ -672,8 +571,15 @@ fn (p mut Parser) module_decl() ast.Module {
|
||||
fn (p mut Parser) import_stmt() ast.Import {
|
||||
p.check(.key_import)
|
||||
name := p.check_name()
|
||||
mut alias := name
|
||||
if p.tok.kind == .key_as {
|
||||
p.check(.key_as)
|
||||
alias = p.check_name()
|
||||
}
|
||||
mut mods := map[string]string
|
||||
mods[alias] = name
|
||||
return ast.Import{
|
||||
mods: [name]
|
||||
mods: mods
|
||||
}
|
||||
}
|
||||
|
||||
@ -700,14 +606,10 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
|
||||
}
|
||||
fields << types.Field{
|
||||
name: field_name
|
||||
type_idx: ti.type_idx
|
||||
type_idx: ti.idx
|
||||
}
|
||||
}
|
||||
p.check(.rcbr)
|
||||
if name in p.table.type_idxs {
|
||||
println('placeholder exists: $name')
|
||||
}
|
||||
println('about to register: $name')
|
||||
p.table.register_struct(types.Struct{
|
||||
name: name
|
||||
fields: fields
|
||||
@ -723,7 +625,7 @@ fn (p mut Parser) return_stmt() ast.Return {
|
||||
p.next()
|
||||
expr,t := p.expr(0)
|
||||
if !types.check(p.return_ti, t) {
|
||||
p.error('cannot use `$t.type_name` as type `$p.return_ti.type_name` in return argument')
|
||||
p.error('cannot use `$t.name` as type `$p.return_ti.name` in return argument')
|
||||
}
|
||||
return ast.Return{
|
||||
expr: expr
|
||||
@ -743,22 +645,22 @@ fn (p mut Parser) var_decl() ast.VarDecl {
|
||||
}
|
||||
name := p.tok.lit
|
||||
p.read_first_token()
|
||||
expr,t := p.expr(token.lowest_prec)
|
||||
expr,ti := p.expr(token.lowest_prec)
|
||||
if _ := p.table.find_var(name) {
|
||||
p.error('redefinition of `$name`')
|
||||
}
|
||||
p.table.register_var(table.Var{
|
||||
name: name
|
||||
ti: t
|
||||
ti: ti
|
||||
is_mut: is_mut
|
||||
})
|
||||
// println(p.table.names)
|
||||
// println('added $name')
|
||||
// println('added var `$name` with type $t.name')
|
||||
return ast.VarDecl{
|
||||
name: name
|
||||
expr: expr // p.expr(token.lowest_prec)
|
||||
|
||||
ti: t
|
||||
ti: ti
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
v.ast
|
||||
v.gen
|
||||
v.table
|
||||
term
|
||||
)
|
||||
|
||||
fn test_parse_file() {
|
||||
@ -27,23 +28,58 @@ x := 10
|
||||
println(res)
|
||||
}
|
||||
|
||||
fn test_parse_expr() {
|
||||
input := [
|
||||
fn test_one() {
|
||||
println('\n\ntest_one()')
|
||||
input := ['a := 10',
|
||||
// 'a = 20',
|
||||
'b := -a',
|
||||
'c := 20',
|
||||
//
|
||||
]
|
||||
expected := 'int a = 10;int b = -a;int c = 20;'
|
||||
table := &table.Table{}
|
||||
mut e := []ast.Stmt
|
||||
for line in input {
|
||||
e << parse_stmt(line, table)
|
||||
}
|
||||
program := ast.File{
|
||||
stmts: e
|
||||
}
|
||||
res := gen.cgen([program], table).replace('\n', '').trim_space()
|
||||
ok := expected == res
|
||||
println(res)
|
||||
assert ok
|
||||
if !ok {}
|
||||
// exit(0)
|
||||
}
|
||||
|
||||
fn test_parse_expr() {
|
||||
input := ['1 == 1',
|
||||
'2 * 8 + 3',
|
||||
'a := 3',
|
||||
'a++',
|
||||
'b := 4 + 2',
|
||||
'neg := -a',
|
||||
'a + a',
|
||||
'bo := 2 + 3 == 5',
|
||||
'2 + 1',
|
||||
'q := 1',
|
||||
'q + 777',
|
||||
'2 + 3',
|
||||
'2+2*4',
|
||||
// '(2+2)*4',
|
||||
'x := 10',
|
||||
'mut a := 12',
|
||||
'mut aa := 12',
|
||||
'ab := 10 + 3 * 9',
|
||||
's := "hi"',
|
||||
// '1 += 2',
|
||||
'x = 11',
|
||||
'a += 10',
|
||||
'1.2 + 3.4',
|
||||
'4 + 4',
|
||||
'1 + 2 * 5',
|
||||
'-a',
|
||||
/*
|
||||
/*
|
||||
'(2 * 3) / 2',
|
||||
'3 + (7 * 6)',
|
||||
@ -52,28 +88,39 @@ fn test_parse_expr() {
|
||||
'(2) + (17*2-30) * (5)+2 - (8/2)*4', // 8
|
||||
//'2 + "hi"',
|
||||
*/
|
||||
*/
|
||||
|
||||
]
|
||||
expecting := [
|
||||
//
|
||||
expecting := ['1 == 1;',
|
||||
'2 * 8 + 3;',
|
||||
'int a = 3;',
|
||||
'a++;',
|
||||
'int b = 4 + 2;',
|
||||
'int neg = -a;',
|
||||
'a + a;',
|
||||
'bool bo = 2 + 3 == 5;',
|
||||
'2 + 1;',
|
||||
'int q = 1;',
|
||||
'q + 777;',
|
||||
'2 + 3;',
|
||||
'2 + 2 * 4;',
|
||||
// '(2 + 2) * 4',
|
||||
'int x = 10;',
|
||||
'int a = 12;',
|
||||
'int aa = 12;',
|
||||
'int ab = 10 + 3 * 9;',
|
||||
'string s = tos3("hi");',
|
||||
// '1 += 2;',
|
||||
'x = 11;',
|
||||
'a += 10;',
|
||||
'1.2 + 3.4;',
|
||||
'4 + 4;',
|
||||
'1 + 2 * 5;',
|
||||
'-a;',
|
||||
]
|
||||
mut e := []ast.Stmt
|
||||
table := &table.Table{}
|
||||
for s in input {
|
||||
// println('\n\nst="$s"')
|
||||
e << parse_stmt(s, table)
|
||||
}
|
||||
program := ast.File{
|
||||
@ -89,8 +136,13 @@ fn test_parse_expr() {
|
||||
if line == '' {
|
||||
continue
|
||||
}
|
||||
println('V:"$line" expecting:"${expecting[i]}"')
|
||||
if line != expecting[i] {
|
||||
println('V:"$line" expecting:"${expecting[i]}"')
|
||||
}
|
||||
assert line == expecting[i]
|
||||
println(term.green('$i OK'))
|
||||
println(line)
|
||||
println('')
|
||||
i++
|
||||
if i >= expecting.len {
|
||||
break
|
||||
|
@ -8,8 +8,8 @@ import (
|
||||
pub struct Table {
|
||||
// struct_fields map[string][]string
|
||||
pub mut:
|
||||
// types map[string]types.Type
|
||||
types []types.Type
|
||||
// type_idxs Hashmap
|
||||
type_idxs map[string]int
|
||||
local_vars []Var
|
||||
// fns Hashmap
|
||||
@ -30,7 +30,7 @@ pub struct Fn {
|
||||
pub:
|
||||
name string
|
||||
args []Var
|
||||
return_ti types.TypeIdent
|
||||
return_ti types.TypeIdent
|
||||
}
|
||||
|
||||
pub fn new_table() &Table {
|
||||
@ -46,7 +46,6 @@ pub fn new_table() &Table {
|
||||
// save index check, 0 will mean not found
|
||||
t.types << types.Type{}
|
||||
t.type_idxs['dymmy_type_at_idx_0'] = 0
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
@ -117,108 +116,6 @@ pub fn (t mut Table) register_fn(new_fn Fn) {
|
||||
t.fns[new_fn.name] = new_fn
|
||||
}
|
||||
|
||||
pub fn (t mut Table) register_struct(typ types.Struct) int {
|
||||
mut t2 := types.Type{}
|
||||
// existing
|
||||
existing_idx := t.type_idxs[typ.name]
|
||||
if existing_idx > 0 {
|
||||
ex_type := t.types[existing_idx]
|
||||
match ex_type {
|
||||
types.Placeholder {
|
||||
// override placeholder
|
||||
println('overriding type placeholder `$it.name` with struct')
|
||||
t2 = {typ| idx: existing_idx}
|
||||
t.types[existing_idx] = t2
|
||||
return existing_idx
|
||||
}
|
||||
types.Struct {
|
||||
return existing_idx
|
||||
}
|
||||
else {
|
||||
panic('cannot register type `$typ.name`, another type with this name exists')
|
||||
}
|
||||
}
|
||||
}
|
||||
// register
|
||||
println('registering: $typ.name')
|
||||
idx := t.types.len
|
||||
t.type_idxs[typ.name] = idx
|
||||
t2 = {typ| idx: idx}
|
||||
t.types << t2
|
||||
|
||||
return idx
|
||||
}
|
||||
|
||||
pub fn (t mut Table) find_or_register_map(typ types.Map) int {
|
||||
// existing
|
||||
existing_idx := t.type_idxs[typ.name]
|
||||
if existing_idx > 0 {
|
||||
return existing_idx
|
||||
}
|
||||
// register
|
||||
idx := t.types.len
|
||||
mut t2 := types.Type{}
|
||||
t2 = {typ| idx: idx}
|
||||
t.type_idxs[typ.name] = idx
|
||||
t.types << t2
|
||||
return idx
|
||||
}
|
||||
|
||||
pub fn (t mut Table) find_or_register_array(typ types.Array) int {
|
||||
// existing
|
||||
existing_idx := t.type_idxs[typ.name]
|
||||
if existing_idx > 0 {
|
||||
return existing_idx
|
||||
}
|
||||
// register
|
||||
idx := t.types.len
|
||||
mut t2 := types.Type{}
|
||||
t2 = {typ| idx: idx}
|
||||
t.type_idxs[typ.name] = idx
|
||||
t.types << t2
|
||||
return idx
|
||||
}
|
||||
|
||||
pub fn (t mut Table) find_or_register_array_fixed(typ types.ArrayFixed) int {
|
||||
// existing
|
||||
existing_idx := t.type_idxs[typ.name]
|
||||
if existing_idx > 0 {
|
||||
return existing_idx
|
||||
}
|
||||
// register
|
||||
idx := t.types.len
|
||||
mut t2 := types.Type{}
|
||||
t2 = {typ| idx: idx}
|
||||
t.type_idxs[typ.name] = idx
|
||||
t.types << t2
|
||||
return idx
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (t &Table) find_type_idx(name string) int {
|
||||
return t.type_idxs[name]
|
||||
}
|
||||
|
||||
pub fn (t mut Table) add_placeholder_type(name string) int {
|
||||
idx := t.types.len
|
||||
t.type_idxs[name] = t.types.len
|
||||
mut pt := types.Type{}
|
||||
pt = types.Placeholder{
|
||||
idx: idx
|
||||
name: name
|
||||
}
|
||||
println('added placeholder: $name - $idx ')
|
||||
t.types << pt
|
||||
return idx
|
||||
}
|
||||
|
||||
pub fn (t &Table) find_type(name string) ?types.Type {
|
||||
idx := t.type_idxs[name]
|
||||
if idx > 0 {
|
||||
return t.types[idx]
|
||||
}
|
||||
return none
|
||||
}
|
||||
|
||||
pub fn (t mut Table) new_tmp_var() string {
|
||||
t.tmp_cnt++
|
||||
|
183
vlib/v/table/type.v
Normal file
183
vlib/v/table/type.v
Normal file
@ -0,0 +1,183 @@
|
||||
// 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.types
|
||||
|
||||
[inline]
|
||||
pub fn (t &Table) find_type_idx(name string) int {
|
||||
return t.type_idxs[name]
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (t &Table) find_type(name string) ?types.Type {
|
||||
idx := t.type_idxs[name]
|
||||
if idx > 0 {
|
||||
return t.types[idx]
|
||||
}
|
||||
return none
|
||||
}
|
||||
|
||||
pub fn (t mut Table) register_struct(typ types.Struct) int {
|
||||
mut struct_type := types.Type{}
|
||||
// existing
|
||||
existing_idx := t.type_idxs[typ.name]
|
||||
if existing_idx > 0 {
|
||||
ex_type := t.types[existing_idx]
|
||||
match ex_type {
|
||||
types.Placeholder {
|
||||
// override placeholder
|
||||
println('overriding type placeholder `$it.name` with struct')
|
||||
struct_type = {
|
||||
typ |
|
||||
idx:existing_idx
|
||||
}
|
||||
t.types[existing_idx] = struct_type
|
||||
return existing_idx
|
||||
}
|
||||
types.Struct {
|
||||
return existing_idx
|
||||
}
|
||||
else {
|
||||
panic('cannot register type `$typ.name`, another type with this name exists')
|
||||
}
|
||||
}
|
||||
}
|
||||
// register
|
||||
println('registering: $typ.name')
|
||||
idx := t.types.len
|
||||
t.type_idxs[typ.name] = idx
|
||||
struct_type = {
|
||||
typ |
|
||||
idx:idx
|
||||
}
|
||||
t.types << struct_type
|
||||
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}'
|
||||
// existing
|
||||
existing_idx := t.type_idxs[name]
|
||||
if existing_idx > 0 {
|
||||
return existing_idx,name
|
||||
}
|
||||
// register
|
||||
idx := t.types.len
|
||||
mut map_type := types.Type{}
|
||||
map_type = types.Map{
|
||||
name: name
|
||||
key_type_idx: key_ti.idx
|
||||
value_type_idx: value_ti.idx
|
||||
}
|
||||
t.type_idxs[name] = idx
|
||||
t.types << 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}_${nr_dims}d'
|
||||
// existing
|
||||
existing_idx := t.type_idxs[name]
|
||||
if existing_idx > 0 {
|
||||
return existing_idx,name
|
||||
}
|
||||
// register
|
||||
idx := t.types.len
|
||||
mut array_type := types.Type{}
|
||||
array_type = types.Array{
|
||||
idx: idx
|
||||
name: name
|
||||
elem_type_idx: elem_ti.idx
|
||||
elem_is_ptr: elem_ti.is_ptr()
|
||||
nr_dims: nr_dims
|
||||
}
|
||||
t.type_idxs[name] = idx
|
||||
t.types << array_type
|
||||
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}_${nr_dims}d'
|
||||
// existing
|
||||
existing_idx := t.type_idxs[name]
|
||||
if existing_idx > 0 {
|
||||
return existing_idx,name
|
||||
}
|
||||
// register
|
||||
idx := t.types.len
|
||||
mut array_fixed_type := types.Type{}
|
||||
array_fixed_type = types.ArrayFixed{
|
||||
idx: idx
|
||||
name: name
|
||||
elem_type_idx: elem_ti.idx
|
||||
elem_is_ptr: elem_ti.is_ptr()
|
||||
size: size
|
||||
nr_dims: nr_dims
|
||||
}
|
||||
t.type_idxs[name] = idx
|
||||
t.types << array_fixed_type
|
||||
return idx,name
|
||||
}
|
||||
|
||||
pub fn (t mut Table) find_or_register_multi_return(mr_tis []&types.TypeIdent) (int,string) {
|
||||
mut name := 'multi_return'
|
||||
mut mr_type_kinds := []types.Kind
|
||||
mut mr_type_idxs := []int
|
||||
for mr_ti in mr_tis {
|
||||
name += '_$mr_ti.name'
|
||||
mr_type_kinds << mr_ti.kind
|
||||
mr_type_idxs << mr_ti.idx
|
||||
}
|
||||
// existing
|
||||
existing_idx := t.type_idxs[name]
|
||||
if existing_idx > 0 {
|
||||
return existing_idx,name
|
||||
}
|
||||
// register
|
||||
idx := t.types.len
|
||||
mut mr_type := types.Type{}
|
||||
mr_type = types.MultiReturn{
|
||||
idx: idx
|
||||
name: name
|
||||
type_kinds: mr_type_kinds
|
||||
type_idxs: mr_type_idxs
|
||||
}
|
||||
t.type_idxs[name] = idx
|
||||
t.types << 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'
|
||||
// existing
|
||||
existing_idx := t.type_idxs[name]
|
||||
if existing_idx > 0 {
|
||||
return existing_idx,name
|
||||
}
|
||||
// register
|
||||
idx := t.types.len
|
||||
mut variadic_type := types.Type{}
|
||||
variadic_type = types.Variadic{
|
||||
idx: idx
|
||||
type_kind: variadic_ti.kind
|
||||
type_idx: variadic_ti.idx
|
||||
}
|
||||
t.type_idxs[name] = idx
|
||||
t.types << variadic_type
|
||||
return idx,name
|
||||
}
|
||||
|
||||
pub fn (t mut Table) add_placeholder_type(name string) int {
|
||||
idx := t.types.len
|
||||
t.type_idxs[name] = t.types.len
|
||||
mut pt := types.Type{}
|
||||
pt = types.Placeholder{
|
||||
idx: idx
|
||||
name: name
|
||||
}
|
||||
println('added placeholder: $name - $idx ')
|
||||
t.types << pt
|
||||
return idx
|
||||
}
|
@ -267,8 +267,8 @@ pub fn is_decl(t Kind) bool {
|
||||
return t in [.key_enum, .key_interface, .key_fn, .key_struct, .key_type, .key_const, .key_import_const, .key_pub, .eof]
|
||||
}
|
||||
|
||||
pub fn (t Token) is_assign() bool {
|
||||
return t.kind in assign_tokens
|
||||
pub fn (t Kind) is_assign() bool {
|
||||
return t in assign_tokens
|
||||
}
|
||||
|
||||
fn (t []Kind) contains(val Kind) bool {
|
||||
@ -308,7 +308,54 @@ pub const (
|
||||
lowest_prec = 0
|
||||
highest_prec = 8
|
||||
)
|
||||
// Precedence returns a tokens precedence if defined, otherwise lowest_prec
|
||||
|
||||
pub enum Precedence {
|
||||
lowest
|
||||
cond // OR or AND
|
||||
assign // =
|
||||
eq // == or !=
|
||||
less_greater // > or <
|
||||
sum // + or -
|
||||
product // * or /
|
||||
mod // %
|
||||
prefix // -X or !X
|
||||
call // func(X) or foo.method(X)
|
||||
index // array[index], map[key]
|
||||
}
|
||||
|
||||
pub fn build_precedences() []Precedence {
|
||||
mut p := []Precedence
|
||||
p = make(100, 100, sizeof(Precedence))
|
||||
p[Kind.assign] = .assign
|
||||
p[Kind.eq] = .eq
|
||||
p[Kind.ne] = .eq
|
||||
p[Kind.lt] = .less_greater
|
||||
p[Kind.gt] = .less_greater
|
||||
p[Kind.le] = .less_greater
|
||||
p[Kind.ge] = .less_greater
|
||||
p[Kind.plus] = .sum
|
||||
p[Kind.plus_assign] = .sum
|
||||
p[Kind.minus] = .sum
|
||||
p[Kind.minus_assign] = .sum
|
||||
p[Kind.div] = .product
|
||||
p[Kind.div_assign] = .product
|
||||
p[Kind.mul] = .product
|
||||
p[Kind.mult_assign] = .product
|
||||
p[Kind.mod] = .mod
|
||||
p[Kind.and] = .cond
|
||||
p[Kind.logical_or] = .cond
|
||||
p[Kind.lpar] = .call
|
||||
p[Kind.dot] = .call
|
||||
p[Kind.lsbr] = .index
|
||||
return p
|
||||
}
|
||||
|
||||
const (
|
||||
precedences = build_precedences()
|
||||
// int(Kind.assign): Precedence.assign
|
||||
// }
|
||||
)
|
||||
// precedence returns a tokens precedence if defined, otherwise lowest_prec
|
||||
pub fn (tok Token) precedence() int {
|
||||
match tok.kind {
|
||||
.dot {
|
||||
@ -316,6 +363,7 @@ pub fn (tok Token) precedence() int {
|
||||
}
|
||||
// `++` | `--`
|
||||
.inc, .dec {
|
||||
// return 0
|
||||
return 7
|
||||
}
|
||||
// `*` | `/` | `%` | `<<` | `>>` | `&`
|
||||
@ -335,7 +383,7 @@ pub fn (tok Token) precedence() int {
|
||||
return 3
|
||||
}
|
||||
// `||`
|
||||
.logical_or {
|
||||
.logical_or, .assign, .plus_assign, .minus_assign, .div_assign, .mult_assign {
|
||||
return 2
|
||||
}
|
||||
// /.plus_assign {
|
||||
@ -366,7 +414,7 @@ pub fn (tok Token) is_left_assoc() bool {
|
||||
return tok.kind in [
|
||||
// `.`
|
||||
.dot,
|
||||
// `+` | `-`
|
||||
// `+` | `-`
|
||||
.plus, .minus, // additive
|
||||
// .number,
|
||||
// `++` | `--`
|
||||
@ -396,8 +444,12 @@ pub fn (tok Token) is_right_assoc() bool {
|
||||
.and_assign, .xor_assign, .or_assign]
|
||||
}
|
||||
|
||||
pub fn (tok Token) is_relational() bool {
|
||||
return tok.kind in [
|
||||
pub fn (tok Kind) is_relational() bool {
|
||||
return tok in [
|
||||
// `<` | `<=` | `>` | `>=`
|
||||
.lt, .le, .gt, .ge, .eq, .ne]
|
||||
}
|
||||
|
||||
pub fn (kind Kind) is_infix() bool {
|
||||
return kind in [.plus, .minus, .mod, .mul, .div, .eq, .ne, .gt, .lt, .ge, .le, .logical_or, .and, .dot]
|
||||
}
|
||||
|
@ -34,27 +34,27 @@ pub enum Kind {
|
||||
|
||||
pub struct TypeIdent {
|
||||
pub:
|
||||
type_idx int
|
||||
type_kind Kind
|
||||
type_name string
|
||||
idx int
|
||||
kind Kind
|
||||
name string
|
||||
nr_muls int
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn new_ti(type_kind Kind, type_name string, type_idx int, nr_muls int) TypeIdent {
|
||||
pub fn new_ti(kind Kind, name string, idx int, nr_muls int) TypeIdent {
|
||||
return TypeIdent{
|
||||
type_idx: type_idx
|
||||
type_kind: type_kind
|
||||
type_name: type_name
|
||||
idx: idx
|
||||
kind: kind
|
||||
name: name
|
||||
nr_muls: nr_muls
|
||||
}
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn new_base_ti(type_kind Kind, nr_muls int) TypeIdent {
|
||||
pub fn new_base_ti(kind Kind, nr_muls int) TypeIdent {
|
||||
return TypeIdent{
|
||||
type_kind: type_kind
|
||||
type_name: type_kind.str()
|
||||
kind: kind
|
||||
name: kind.str()
|
||||
nr_muls: nr_muls
|
||||
}
|
||||
}
|
||||
@ -66,12 +66,12 @@ pub fn (ti &TypeIdent) is_ptr() bool {
|
||||
|
||||
[inline]
|
||||
pub fn (ti &TypeIdent) is_int() bool {
|
||||
return ti.type_kind in [._i8, ._i16, ._int, ._i64, ._byte, ._u16, ._u32, ._u64]
|
||||
return ti.kind in [._i8, ._i16, ._int, ._i64, ._byte, ._u16, ._u32, ._u64]
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub fn (ti &TypeIdent) is_float() bool {
|
||||
return ti.type_kind in [._f32, ._f64]
|
||||
return ti.kind in [._f32, ._f64]
|
||||
}
|
||||
|
||||
[inline]
|
||||
@ -80,18 +80,18 @@ pub fn (ti &TypeIdent) is_number() bool {
|
||||
}
|
||||
|
||||
pub fn (ti &TypeIdent) str() string {
|
||||
return '$ti.type_kind.str() $ti.type_idx: $ti.type_name ($ti.nr_muls)'
|
||||
return '$ti.kind.str() $ti.idx: $ti.name ($ti.nr_muls)'
|
||||
}
|
||||
|
||||
pub fn check(got, expected &TypeIdent) bool {
|
||||
if got.type_idx != expected.type_idx {
|
||||
if got.idx != expected.idx {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
pub fn (t Kind) str() string {
|
||||
t_str := match t {
|
||||
pub fn (k Kind) str() string {
|
||||
k_str := match k {
|
||||
._placeholder {
|
||||
'placeholder'
|
||||
}
|
||||
@ -168,7 +168,18 @@ pub fn (t Kind) str() string {
|
||||
'unknown'
|
||||
}
|
||||
}
|
||||
return t_str
|
||||
return k_str
|
||||
}
|
||||
|
||||
pub fn (kinds []Kind) str() string {
|
||||
mut kinds_str := ''
|
||||
for i, k in kinds {
|
||||
kinds_str += k.str()
|
||||
if i < kinds.len-1 {
|
||||
kinds_str += '_'
|
||||
}
|
||||
}
|
||||
return kinds_str
|
||||
}
|
||||
|
||||
pub type Type = Placeholder | Void | Voidptr | Charptr | Byteptr | Const | Enum | Struct |
|
||||
@ -179,7 +190,7 @@ pub struct Placeholder {
|
||||
pub:
|
||||
idx int
|
||||
name string
|
||||
kind Kind
|
||||
// kind Kind
|
||||
}
|
||||
|
||||
pub struct Void {}
|
||||
@ -250,6 +261,7 @@ pub:
|
||||
elem_type_kind Kind
|
||||
elem_type_idx int
|
||||
elem_is_ptr bool
|
||||
nr_dims int
|
||||
size int
|
||||
}
|
||||
|
||||
@ -265,14 +277,17 @@ pub:
|
||||
|
||||
pub struct MultiReturn {
|
||||
pub:
|
||||
elem_type_kinds []Kind
|
||||
elem_type_idxs []int
|
||||
idx int
|
||||
name string
|
||||
type_kinds []Kind
|
||||
type_idxs []int
|
||||
}
|
||||
|
||||
pub struct Variadic {
|
||||
pub:
|
||||
elem_type_kind Kind
|
||||
elem_type_idx int
|
||||
idx int
|
||||
type_kind Kind
|
||||
type_idx int
|
||||
}
|
||||
|
||||
pub fn (t Void) str() string { return 'void' }
|
||||
@ -290,8 +305,8 @@ pub fn (t Byte) str() string { return 'byte' }
|
||||
pub fn (t Array) str() string { return t.name }
|
||||
pub fn (t ArrayFixed) str() string { return t.name }
|
||||
pub fn (t Map) str() string { return t.name }
|
||||
pub fn (t MultiReturn) str() string { return 'multi_return_$t.elem_type_kinds.str()' }
|
||||
pub fn (t Variadic) str() string { return 'variadic_$t.elem_type_kind.str()' }
|
||||
pub fn (t MultiReturn) str() string { return t.name }
|
||||
pub fn (t Variadic) str() string { return 'variadic_$t.type_kind.str()' }
|
||||
|
||||
pub const (
|
||||
void_type = Void{}
|
||||
@ -312,3 +327,10 @@ pub const (
|
||||
char_type = Char{}
|
||||
bool_type = Bool{}
|
||||
)
|
||||
|
||||
pub const (
|
||||
void_ti = new_base_ti(._void, 0)
|
||||
int_ti = new_base_ti(._int, 0)
|
||||
string_ti = new_base_ti(._string, 0)
|
||||
bool_ti = new_base_ti(._bool, 0)
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user