simplify and improve pratt
parent
025efcb731
commit
b815878d60
|
@ -38,7 +38,7 @@ fn expr1() Expr {
|
||||||
//return BinExpr{}
|
//return BinExpr{}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expr2() Expr {
|
fn expr() Expr {
|
||||||
return BinExpr{}
|
return BinExpr{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
pub type Expr = BinaryExpr | UnaryExpr | IfExpr | StringLiteral | IntegerLiteral |
|
pub type Expr = BinaryExpr | UnaryExpr | IfExpr | StringLiteral | IntegerLiteral |
|
||||||
FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr
|
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
|
ForStmt | StructDecl
|
||||||
|
// | IncDecStmt k
|
||||||
// Stand-alone expression in a statement list.
|
// Stand-alone expression in a statement list.
|
||||||
pub struct ExprStmt {
|
pub struct ExprStmt {
|
||||||
pub:
|
pub:
|
||||||
|
@ -71,8 +72,8 @@ pub:
|
||||||
|
|
||||||
pub struct StructInit {
|
pub struct StructInit {
|
||||||
pub:
|
pub:
|
||||||
ti types.TypeIdent
|
// typ types.TypeIdent
|
||||||
// typ types.Type
|
ti types.TypeIdent
|
||||||
fields []string
|
fields []string
|
||||||
exprs []Expr
|
exprs []Expr
|
||||||
}
|
}
|
||||||
|
@ -80,26 +81,23 @@ pub:
|
||||||
// import statement
|
// import statement
|
||||||
pub struct Import {
|
pub struct Import {
|
||||||
pub:
|
pub:
|
||||||
mods []string
|
mods map[string]string // alias -> module
|
||||||
// expr Expr
|
// expr Expr
|
||||||
// imports map[string]string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Arg {
|
pub struct Arg {
|
||||||
pub:
|
pub:
|
||||||
ti types.TypeIdent
|
ti types.TypeIdent
|
||||||
// typ types.Type
|
|
||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FnDecl {
|
pub struct FnDecl {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
stmts []Stmt
|
stmts []Stmt
|
||||||
ti types.TypeIdent
|
ti types.TypeIdent
|
||||||
// typ types.Type
|
args []Arg
|
||||||
args []Arg
|
is_pub bool
|
||||||
is_pub bool
|
|
||||||
receiver Field
|
receiver Field
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +135,6 @@ pub:
|
||||||
name string
|
name string
|
||||||
expr Expr
|
expr Expr
|
||||||
ti types.TypeIdent
|
ti types.TypeIdent
|
||||||
// typ types.Type
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct File {
|
pub struct File {
|
||||||
|
@ -159,9 +156,9 @@ pub:
|
||||||
// op BinaryOp
|
// op BinaryOp
|
||||||
op token.Kind
|
op token.Kind
|
||||||
left Expr
|
left Expr
|
||||||
// left_type Type
|
// left_ti types.TypeIdent
|
||||||
right Expr
|
right Expr
|
||||||
// right_type Type
|
// right_ti types.TypeIdent
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UnaryExpr {
|
pub struct UnaryExpr {
|
||||||
|
@ -172,6 +169,18 @@ pub:
|
||||||
left Expr
|
left Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct PostfixExpr {
|
||||||
|
pub:
|
||||||
|
op token.Kind
|
||||||
|
expr Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PrefixExpr {
|
||||||
|
pub:
|
||||||
|
op token.Kind
|
||||||
|
right Expr
|
||||||
|
}
|
||||||
|
|
||||||
pub struct IfExpr {
|
pub struct IfExpr {
|
||||||
pub:
|
pub:
|
||||||
tok_kind token.Kind
|
tok_kind token.Kind
|
||||||
|
@ -179,7 +188,6 @@ pub:
|
||||||
stmts []Stmt
|
stmts []Stmt
|
||||||
else_stmts []Stmt
|
else_stmts []Stmt
|
||||||
ti types.TypeIdent
|
ti types.TypeIdent
|
||||||
// typ types.Type
|
|
||||||
left Expr // `a` in `a := if ...`
|
left Expr // `a` in `a := if ...`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,11 +210,17 @@ pub:
|
||||||
op token.Kind
|
op token.Kind
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct AssignExpr {
|
||||||
|
pub:
|
||||||
|
left Expr
|
||||||
|
val Expr
|
||||||
|
op token.Kind
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ArrayInit {
|
pub struct ArrayInit {
|
||||||
pub:
|
pub:
|
||||||
exprs []Expr
|
exprs []Expr
|
||||||
ti types.TypeIdent
|
ti types.TypeIdent
|
||||||
// typ types.Type
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// string representaiton of expr
|
// string representaiton of expr
|
||||||
|
|
|
@ -14,6 +14,7 @@ struct Gen {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cgen(files []ast.File, table &table.Table) string {
|
pub fn cgen(files []ast.File, table &table.Table) string {
|
||||||
|
println('start cgen')
|
||||||
mut g := Gen{
|
mut g := Gen{
|
||||||
out: strings.new_builder(100)
|
out: strings.new_builder(100)
|
||||||
definitions: 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) {
|
fn (g mut Gen) stmt(node ast.Stmt) {
|
||||||
|
// println('cgen.stmt()')
|
||||||
|
// g.writeln('//// stmt start')
|
||||||
match node {
|
match node {
|
||||||
|
ast.Import {
|
||||||
|
|
||||||
|
}
|
||||||
|
/*
|
||||||
ast.AssignStmt {
|
ast.AssignStmt {
|
||||||
g.expr(it.left)
|
g.expr(it.left)
|
||||||
g.write(' $it.op.str() ')
|
g.write(' $it.op.str() ')
|
||||||
g.expr(it.right)
|
g.expr(it.right)
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
ast.FnDecl {
|
ast.FnDecl {
|
||||||
is_main := it.name == 'main'
|
is_main := it.name == 'main'
|
||||||
if is_main {
|
if is_main {
|
||||||
g.write('int ${it.name}(')
|
g.write('int ${it.name}(')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g.write('$it.ti.type_name ${it.name}(')
|
g.write('$it.ti.name ${it.name}(')
|
||||||
g.definitions.write('$it.ti.type_name ${it.name}(')
|
g.definitions.write('$it.ti.name ${it.name}(')
|
||||||
}
|
}
|
||||||
for arg in it.args {
|
for arg in it.args {
|
||||||
g.write(arg.ti.type_name + ' ' + arg.name)
|
g.write(arg.ti.name + ' ' + arg.name)
|
||||||
g.definitions.write(arg.ti.type_name + ' ' + arg.name)
|
g.definitions.write(arg.ti.name + ' ' + arg.name)
|
||||||
}
|
}
|
||||||
g.writeln(') { ')
|
g.writeln(') { ')
|
||||||
if !is_main {
|
if !is_main {
|
||||||
|
@ -77,7 +85,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
ast.VarDecl {
|
ast.VarDecl {
|
||||||
g.write('$it.ti.type_name $it.name = ')
|
g.write('$it.ti.name $it.name = ')
|
||||||
g.expr(it.expr)
|
g.expr(it.expr)
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
|
@ -97,7 +105,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||||
ast.StructDecl {
|
ast.StructDecl {
|
||||||
g.writeln('typedef struct {')
|
g.writeln('typedef struct {')
|
||||||
for field in it.fields {
|
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;')
|
g.writeln('} $it.name;')
|
||||||
}
|
}
|
||||||
|
@ -120,12 +128,21 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||||
fn (g mut Gen) expr(node ast.Expr) {
|
fn (g mut Gen) expr(node ast.Expr) {
|
||||||
// println('cgen expr()')
|
// println('cgen expr()')
|
||||||
match node {
|
match node {
|
||||||
|
ast.AssignExpr {
|
||||||
|
g.expr(it.left)
|
||||||
|
g.write(' $it.op.str() ')
|
||||||
|
g.expr(it.val)
|
||||||
|
}
|
||||||
ast.IntegerLiteral {
|
ast.IntegerLiteral {
|
||||||
g.write(it.val.str())
|
g.write(it.val.str())
|
||||||
}
|
}
|
||||||
ast.FloatLiteral {
|
ast.FloatLiteral {
|
||||||
g.write(it.val)
|
g.write(it.val)
|
||||||
}
|
}
|
||||||
|
ast.PostfixExpr {
|
||||||
|
g.expr(it.expr)
|
||||||
|
g.write(it.op.str())
|
||||||
|
}
|
||||||
ast.UnaryExpr {
|
ast.UnaryExpr {
|
||||||
// probably not :D
|
// probably not :D
|
||||||
if it.op in [.inc, .dec] {
|
if it.op in [.inc, .dec] {
|
||||||
|
@ -140,6 +157,10 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
ast.StringLiteral {
|
ast.StringLiteral {
|
||||||
g.write('tos3("$it.val")')
|
g.write('tos3("$it.val")')
|
||||||
}
|
}
|
||||||
|
ast.PrefixExpr {
|
||||||
|
g.write(it.op.str())
|
||||||
|
g.expr(it.right)
|
||||||
|
}
|
||||||
ast.BinaryExpr {
|
ast.BinaryExpr {
|
||||||
g.expr(it.left)
|
g.expr(it.left)
|
||||||
if it.op == .dot {
|
if it.op == .dot {
|
||||||
|
@ -153,7 +174,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
// `user := User{name: 'Bob'}`
|
// `user := User{name: 'Bob'}`
|
||||||
ast.StructInit {
|
ast.StructInit {
|
||||||
g.writeln('($it.ti.type_name){')
|
g.writeln('($it.ti.name){')
|
||||||
for i, field in it.fields {
|
for i, field in it.fields {
|
||||||
g.write('\t.$field = ')
|
g.write('\t.$field = ')
|
||||||
g.expr(it.exprs[i])
|
g.expr(it.exprs[i])
|
||||||
|
@ -172,7 +193,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
ast.ArrayInit {
|
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 {
|
for expr in it.exprs {
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
|
@ -199,16 +220,16 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
// If expression? Assign the value to a temp var.
|
// If expression? Assign the value to a temp var.
|
||||||
// Previously ?: was used, but it's too unreliable.
|
// Previously ?: was used, but it's too unreliable.
|
||||||
mut tmp := ''
|
mut tmp := ''
|
||||||
if it.ti.type_kind != ._void {
|
if it.ti.kind != ._void {
|
||||||
tmp = g.table.new_tmp_var()
|
tmp = g.table.new_tmp_var()
|
||||||
// g.writeln('$it.typ.name $tmp;')
|
// g.writeln('$it.ti.name $tmp;')
|
||||||
}
|
}
|
||||||
g.write('if (')
|
g.write('if (')
|
||||||
g.expr(it.cond)
|
g.expr(it.cond)
|
||||||
g.writeln(') {')
|
g.writeln(') {')
|
||||||
for i, stmt in it.stmts {
|
for i, stmt in it.stmts {
|
||||||
// Assign ret value
|
// 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 =')
|
// g.writeln('$tmp =')
|
||||||
println(1)
|
println(1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
nr_tests = 2
|
nr_tests = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
fn test_c_files() {
|
fn test_c_files() {
|
||||||
|
|
|
@ -40,9 +40,9 @@ fn (g mut JsGen) stmt(node ast.Stmt) {
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
ast.FnDecl {
|
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 {
|
for arg in it.args {
|
||||||
g.write(' /** @type { arg.ti.type_name } **/ $arg.name')
|
g.write(' /** @type { arg.ti.name } **/ $arg.name')
|
||||||
}
|
}
|
||||||
g.writeln(') { ')
|
g.writeln(') { ')
|
||||||
for stmt in it.stmts {
|
for stmt in it.stmts {
|
||||||
|
@ -56,7 +56,7 @@ fn (g mut JsGen) stmt(node ast.Stmt) {
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
ast.VarDecl {
|
ast.VarDecl {
|
||||||
g.write('var /* $it.ti.type_name */ $it.name = ')
|
g.write('var /* $it.ti.name */ $it.name = ')
|
||||||
g.expr(it.expr)
|
g.expr(it.expr)
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ fn (g mut JsGen) stmt(node ast.Stmt) {
|
||||||
ast.StructDecl {
|
ast.StructDecl {
|
||||||
// g.writeln('typedef struct {')
|
// g.writeln('typedef struct {')
|
||||||
// for field in it.fields {
|
// 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() {};')
|
g.writeln('var $it.name = function() {};')
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ fn (g mut JsGen) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
// `user := User{name: 'Bob'}`
|
// `user := User{name: 'Bob'}`
|
||||||
ast.StructInit {
|
ast.StructInit {
|
||||||
g.writeln('/*$it.ti.type_name*/{')
|
g.writeln('/*$it.ti.name*/{')
|
||||||
for i, field in it.fields {
|
for i, field in it.fields {
|
||||||
g.write('\t$field : ')
|
g.write('\t$field : ')
|
||||||
g.expr(it.exprs[i])
|
g.expr(it.exprs[i])
|
||||||
|
|
|
@ -10,9 +10,10 @@ typedef struct {
|
||||||
int main() {
|
int main() {
|
||||||
int a = 10;
|
int a = 10;
|
||||||
a++;
|
a++;
|
||||||
int c = -a;
|
int negative = -a;
|
||||||
a == 1;
|
a == 1;
|
||||||
foo(3);
|
foo(3);
|
||||||
|
int ak = 10;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,4 +38,8 @@ void myuser() {
|
||||||
int boo = 2;
|
int boo = 2;
|
||||||
int boo2 = boo + 1;
|
int boo2 = boo + 1;
|
||||||
bool b = age > 0;
|
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 {
|
struct User {
|
||||||
age int
|
age int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lol
|
||||||
fn main() {
|
fn main() {
|
||||||
a := 10
|
a := 10
|
||||||
a++
|
a++
|
||||||
c := -a
|
negative := -a
|
||||||
a == 1
|
a == 1
|
||||||
foo(3)
|
foo(3)
|
||||||
|
ak := 10
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
user := User{}
|
user := User{}
|
||||||
user.age = 10
|
user.age = 10
|
||||||
|
@ -16,7 +22,6 @@ fn main() {
|
||||||
|
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
|
||||||
|
|
||||||
fn foo(a int) {
|
fn foo(a int) {
|
||||||
n := get_int2()
|
n := get_int2()
|
||||||
|
@ -37,5 +42,8 @@ fn myuser() {
|
||||||
boo := 2
|
boo := 2
|
||||||
boo2 := boo+1
|
boo2 := boo+1
|
||||||
b := age > 0
|
b := age > 0
|
||||||
//b2 := user.age > 0
|
b2 := user.age > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn variadic(a ...int) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
ast.VarDecl {
|
ast.VarDecl {
|
||||||
g.write('$it.ti.type_name $it.name = ')
|
g.write('$it.ti.name $it.name = ')
|
||||||
g.expr(it.expr)
|
g.expr(it.expr)
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
|
@ -354,7 +354,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||||
ast.StructDecl {
|
ast.StructDecl {
|
||||||
g.writeln('typedef struct {')
|
g.writeln('typedef struct {')
|
||||||
for field in it.fields {
|
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;')
|
g.writeln('} $it.name;')
|
||||||
}
|
}
|
||||||
|
@ -400,7 +400,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
// `user := User{name: 'Bob'}`
|
// `user := User{name: 'Bob'}`
|
||||||
ast.StructInit {
|
ast.StructInit {
|
||||||
g.writeln('($it.ti.type_name){')
|
g.writeln('($it.ti.name){')
|
||||||
for i, field in it.fields {
|
for i, field in it.fields {
|
||||||
g.write('\t.$field = ')
|
g.write('\t.$field = ')
|
||||||
g.expr(it.exprs[i])
|
g.expr(it.exprs[i])
|
||||||
|
@ -426,7 +426,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
|
|
||||||
}
|
}
|
||||||
ast.ArrayInit {
|
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 {
|
for expr in it.exprs {
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
|
|
|
@ -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()
|
fn_name := p.check_name()
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
mut is_unknown := false
|
mut is_unknown := false
|
||||||
|
is_unknown = false
|
||||||
mut args := []ast.Expr
|
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) {
|
if f := p.table.find_fn(fn_name) {
|
||||||
return_ti = f.return_ti
|
return_ti = f.return_ti
|
||||||
for i, arg in f.args {
|
for i, arg in f.args {
|
||||||
e,ti := p.expr(0)
|
e,ti := p.expr(0)
|
||||||
if !types.check(arg.ti, ti) {
|
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`')
|
p.error('cannot use type `$ti.name` as type `$arg.ti.name` in argument to `$fn_name`')
|
||||||
}
|
}
|
||||||
args << e
|
args << e
|
||||||
if i < f.args.len - 1 {
|
if i < f.args.len - 1 {
|
||||||
|
@ -49,7 +50,7 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,types.TypeIdent) {
|
||||||
args: args
|
args: args
|
||||||
is_unknown: is_unknown
|
is_unknown: is_unknown
|
||||||
tok: tok
|
tok: tok
|
||||||
// typ: return_type
|
// typ: return_ti
|
||||||
|
|
||||||
}
|
}
|
||||||
if is_unknown {
|
if is_unknown {
|
||||||
|
@ -67,7 +68,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
p.check(.key_fn)
|
p.check(.key_fn)
|
||||||
// Receiver?
|
// Receiver?
|
||||||
mut rec_name := ''
|
mut rec_name := ''
|
||||||
mut rec_ti := types.new_base_ti(._void, 0)
|
mut rec_ti := types.void_ti
|
||||||
if p.tok.kind == .lpar {
|
if p.tok.kind == .lpar {
|
||||||
p.next()
|
p.next()
|
||||||
rec_name = p.check_name()
|
rec_name = p.check_name()
|
||||||
|
@ -113,8 +114,8 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
}
|
}
|
||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
// Return type
|
// Return type
|
||||||
mut ti := types.new_base_ti(._void, 0)
|
mut ti := types.void_ti
|
||||||
if p.tok.kind in [.amp, .name] {
|
if p.tok.kind == .name {
|
||||||
ti = p.parse_ti()
|
ti = p.parse_ti()
|
||||||
p.return_ti = ti
|
p.return_ti = ti
|
||||||
}
|
}
|
||||||
|
@ -145,7 +146,7 @@ pub fn (p &Parser) check_fn_calls() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
println(f.name)
|
println(f.name)
|
||||||
// println(f.return_type.name)
|
// println(f.return_ti.name)
|
||||||
// println('IN AST typ=' + call.typ.name)
|
// println('IN AST typ=' + call.typ.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,16 +13,24 @@ import (
|
||||||
os
|
os
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type PrefixParseFn fn()ast.Expr
|
||||||
|
|
||||||
|
type InfixParseFn fn(e ast.Expr)ast.Expr
|
||||||
|
|
||||||
|
type PostfixParseFn fn()ast.Expr
|
||||||
|
|
||||||
struct Parser {
|
struct Parser {
|
||||||
scanner &scanner.Scanner
|
scanner &scanner.Scanner
|
||||||
file_name string
|
file_name string
|
||||||
mut:
|
mut:
|
||||||
tok token.Token
|
tok token.Token
|
||||||
peek_tok token.Token
|
peek_tok token.Token
|
||||||
// vars []string
|
// vars []string
|
||||||
table &table.Table
|
table &table.Table
|
||||||
return_ti types.TypeIdent
|
return_ti types.TypeIdent
|
||||||
is_c bool
|
is_c bool
|
||||||
|
//
|
||||||
|
prefix_parse_fns []PrefixParseFn
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_stmt(text string, table &table.Table) ast.Stmt {
|
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
|
scanner: s
|
||||||
table: table
|
table: table
|
||||||
}
|
}
|
||||||
|
p.init_parse_fns()
|
||||||
p.read_first_token()
|
p.read_first_token()
|
||||||
return p.stmt()
|
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 {
|
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 {
|
text := os.read_file(path) or {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -173,12 +59,11 @@ pub fn parse_file(path string, table &table.Table) ast.File {
|
||||||
for {
|
for {
|
||||||
// res := s.scan()
|
// res := s.scan()
|
||||||
if p.tok.kind == .eof {
|
if p.tok.kind == .eof {
|
||||||
|
println('EOF, breaking')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// println('expr at ' + p.tok.str())
|
// println('stmt at ' + p.tok.str())
|
||||||
s := p.stmt()
|
stmts << p.top_stmt()
|
||||||
// println(s)
|
|
||||||
stmts << s // p.stmt()
|
|
||||||
}
|
}
|
||||||
p.check_fn_calls()
|
p.check_fn_calls()
|
||||||
// println('nr stmts = $stmts.len')
|
// println('nr stmts = $stmts.len')
|
||||||
|
@ -196,6 +81,11 @@ pub fn parse_files(paths []string, table &table.Table) []ast.File {
|
||||||
return files
|
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() {
|
pub fn (p mut Parser) read_first_token() {
|
||||||
// need to call next() twice to get peek token and current token
|
// need to call next() twice to get peek token and current token
|
||||||
p.next()
|
p.next()
|
||||||
|
@ -205,13 +95,14 @@ pub fn (p mut Parser) read_first_token() {
|
||||||
pub fn (p mut Parser) parse_block() []ast.Stmt {
|
pub fn (p mut Parser) parse_block() []ast.Stmt {
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
mut stmts := []ast.Stmt
|
mut stmts := []ast.Stmt
|
||||||
for {
|
if p.tok.kind != .rcbr {
|
||||||
// res := s.scan()
|
for {
|
||||||
if p.tok.kind in [.eof, .rcbr] {
|
stmts << p.stmt()
|
||||||
break
|
// 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)
|
p.check(.rcbr)
|
||||||
// println('nr exprs in block = $exprs.len')
|
// println('nr exprs in block = $exprs.len')
|
||||||
|
@ -238,17 +129,7 @@ fn (p mut Parser) check_name() string {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (p mut Parser) stmt() ast.Stmt {
|
pub fn (p mut Parser) top_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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
match p.tok.kind {
|
match p.tok.kind {
|
||||||
.key_module {
|
.key_module {
|
||||||
return p.module_decl()
|
return p.module_decl()
|
||||||
|
@ -285,16 +166,30 @@ pub fn (p mut Parser) stmt() ast.Stmt {
|
||||||
.key_struct {
|
.key_struct {
|
||||||
return p.struct_decl()
|
return p.struct_decl()
|
||||||
}
|
}
|
||||||
.key_return {
|
else {
|
||||||
return p.return_stmt()
|
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 {
|
.key_mut {
|
||||||
return p.var_decl()
|
return p.var_decl()
|
||||||
}
|
}
|
||||||
.key_for {
|
.key_for {
|
||||||
return p.for_statement()
|
return p.for_statement()
|
||||||
}
|
}
|
||||||
|
.key_return {
|
||||||
|
return p.return_stmt()
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
|
// `x := ...`
|
||||||
|
if p.tok.kind == .name && p.peek_tok.kind == .decl_assign {
|
||||||
|
return p.var_decl()
|
||||||
|
}
|
||||||
expr,ti := p.expr(0)
|
expr,ti := p.expr(0)
|
||||||
return ast.ExprStmt{
|
return ast.ExprStmt{
|
||||||
expr: expr
|
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 {
|
pub fn (p mut Parser) assign_stmt() ast.AssignStmt {
|
||||||
name := p.tok.lit
|
name := p.tok.lit
|
||||||
// println('looking for $name')
|
// println('looking for $name')
|
||||||
var := p.table.find_var(name) or {
|
var := p.table.find_var(name) or {
|
||||||
p.error('unknown variable `$name`')
|
p.error('assign unknown variable `$name`')
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
if !var.is_mut {
|
if !var.is_mut {
|
||||||
|
@ -328,6 +236,8 @@ pub fn (p mut Parser) assign_stmt() ast.AssignStmt {
|
||||||
op: op
|
op: op
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
pub fn (p &Parser) error(s string) {
|
pub fn (p &Parser) error(s string) {
|
||||||
println(term.bold(term.red('$p.file_name:$p.tok.line_nr: $s')))
|
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'))
|
println(term.blue('$p.file_name:$p.tok.line_nr: $s'))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implementation of Pratt Precedence
|
pub fn (p mut Parser) name_expr() (ast.Expr,types.TypeIdent) {
|
||||||
pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.TypeIdent) {
|
|
||||||
// println('expr at ' + p.tok.str())
|
|
||||||
// null denotation (prefix)
|
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
// mut typ := types.void_type
|
mut ti := types.void_ti
|
||||||
mut ti := types.new_base_ti(._void, 0)
|
// 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 {
|
match p.tok.kind {
|
||||||
.name {
|
.name {
|
||||||
/*
|
node,ti = p.name_expr()
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.lsbr {
|
.str {
|
||||||
node,ti = p.array_init()
|
node,ti = p.parse_string_literal()
|
||||||
|
}
|
||||||
|
// -1, -a etc
|
||||||
|
.minus {
|
||||||
|
node,ti = p.prefix_expr()
|
||||||
}
|
}
|
||||||
.key_true, .key_false {
|
.key_true, .key_false {
|
||||||
node = ast.BoolLiteral{
|
node = ast.BoolLiteral{
|
||||||
val: p.tok.kind == .key_true
|
val: p.tok.kind == .key_true
|
||||||
}
|
}
|
||||||
ti = types.new_base_ti(._bool, 0)
|
ti = types.bool_ti
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
.str {
|
|
||||||
node,ti = p.parse_string_literal()
|
|
||||||
}
|
|
||||||
.number {
|
.number {
|
||||||
node,ti = p.parse_number_literal()
|
node,ti = p.parse_number_literal()
|
||||||
}
|
}
|
||||||
.key_if {
|
|
||||||
node,ti = p.if_expr()
|
|
||||||
}
|
|
||||||
.lpar {
|
.lpar {
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
p.next()
|
p.next()
|
||||||
node,ti = p.expr(token.lowest_prec)
|
node,ti = p.expr(0)
|
||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
}
|
}
|
||||||
|
.key_if {
|
||||||
|
node,ti = p.if_expr()
|
||||||
|
}
|
||||||
|
.lsbr {
|
||||||
|
node,ti = p.array_init()
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if p.tok.is_unary() {
|
p.error('expr(): bad token `$p.tok.str()`')
|
||||||
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')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// left binding power
|
// Infix
|
||||||
for rbp < p.tok.precedence() {
|
for precedence < p.tok.precedence() {
|
||||||
prev_tok := p.tok
|
if p.tok.kind.is_assign() {
|
||||||
p.next()
|
node = p.assign_expr(node)
|
||||||
// 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`')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if prev_tok.is_left_assoc() {
|
else if p.tok.kind == .dot {
|
||||||
// postfix `.`
|
node,ti = p.dot_expr(node)
|
||||||
if prev_tok.kind == .dot {
|
}
|
||||||
p.warn('dot prev_tok = $prev_tok.str() typ=$ti.type_name')
|
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()
|
// p.next()
|
||||||
field := p.check_name()
|
field := p.check_name()
|
||||||
if !ti.type_kind in [._placeholder, ._struct] {
|
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 {
|
if !ok {
|
||||||
p.error('unknown field `${typ.name}.$field`')
|
p.error('unknown field `${typ.name}.$field`')
|
||||||
}
|
}
|
||||||
node = ast.SelectorExpr{
|
*/
|
||||||
expr: node
|
|
||||||
field: field
|
mut node := ast.Expr{}
|
||||||
}
|
node = ast.SelectorExpr{
|
||||||
// return node,typ
|
expr: left
|
||||||
}
|
field: field_name
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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]
|
[inline]
|
||||||
fn (p &Parser) is_addative() bool {
|
fn (p &Parser) is_addative() bool {
|
||||||
return p.tok.kind in [.plus, .minus] && p.peek_tok.kind in [.number, .name]
|
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 {`
|
// `for cond {`
|
||||||
cond,ti := p.expr(0)
|
cond,ti := p.expr(0)
|
||||||
// if !types.check(types.bool_type, ti) {
|
if !types.check(types.bool_ti, ti) {
|
||||||
if ti.type_kind != ._bool {
|
|
||||||
p.error('non-bool used as for condition')
|
p.error('non-bool used as for condition')
|
||||||
}
|
}
|
||||||
stmts := p.parse_block()
|
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) {
|
fn (p mut Parser) if_expr() (ast.Expr,types.TypeIdent) {
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
p.check(.key_if)
|
p.check(.key_if)
|
||||||
cond,cond_type := p.expr(0)
|
cond,cond_ti := p.expr(0)
|
||||||
// if !types.check(types.bool_type, cond_type) {
|
// if !types.check(types.bool_ti, cond_ti) {
|
||||||
if cond_type.type_kind != ._bool {
|
if cond_ti.kind != ._bool {
|
||||||
p.error('non-bool used as if condition')
|
p.error('non-bool used as if condition')
|
||||||
}
|
}
|
||||||
stmts := p.parse_block()
|
stmts := p.parse_block()
|
||||||
mut else_stmts := []ast.Stmt
|
mut else_stmts := []ast.Stmt
|
||||||
if p.tok.kind == .key_else {
|
if p.tok.kind == .key_else {
|
||||||
// println('GOT ELSE')
|
|
||||||
p.check(.key_else)
|
p.check(.key_else)
|
||||||
else_stmts = p.parse_block()
|
else_stmts = p.parse_block()
|
||||||
}
|
}
|
||||||
// mut typ := types.void_type
|
mut ti := types.void_ti
|
||||||
mut ti := types.new_base_ti(._void, 0)
|
|
||||||
// mut left := ast.Expr{}
|
// mut left := ast.Expr{}
|
||||||
// If the last statement is an expression, return its type
|
// If the last statement is an expression, return its type
|
||||||
match stmts[stmts.len - 1] {
|
match stmts[stmts.len - 1] {
|
||||||
ast.ExprStmt {
|
ast.ExprStmt {
|
||||||
p.warn('if expr ret $it.ti.type_name')
|
p.warn('if expr ret $it.ti.name')
|
||||||
ti = it.ti
|
ti = it.ti
|
||||||
// return node,it.typ
|
// return node,it.ti
|
||||||
// left =
|
// left =
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
|
@ -608,14 +509,12 @@ fn (p mut Parser) parse_string_literal() (ast.Expr,types.TypeIdent) {
|
||||||
val: p.tok.lit
|
val: p.tok.lit
|
||||||
}
|
}
|
||||||
p.next()
|
p.next()
|
||||||
// return node,types.string_type
|
return node,types.string_ti
|
||||||
return node, types.new_base_ti(._string, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) array_init() (ast.Expr,types.TypeIdent) {
|
fn (p mut Parser) array_init() (ast.Expr,types.TypeIdent) {
|
||||||
p.check(.lsbr)
|
p.check(.lsbr)
|
||||||
// mut val_type := types.void_type
|
mut val_ti := types.void_ti
|
||||||
mut val_ti := types.new_base_ti(._void, 0)
|
|
||||||
mut exprs := []ast.Expr
|
mut exprs := []ast.Expr
|
||||||
mut i := 0
|
mut i := 0
|
||||||
for p.tok.kind != .rsbr {
|
for p.tok.kind != .rsbr {
|
||||||
|
@ -625,7 +524,7 @@ fn (p mut Parser) array_init() (ast.Expr,types.TypeIdent) {
|
||||||
val_ti = ti
|
val_ti = ti
|
||||||
}
|
}
|
||||||
else if !types.check(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
|
exprs << expr
|
||||||
i++
|
i++
|
||||||
|
@ -672,8 +571,15 @@ fn (p mut Parser) module_decl() ast.Module {
|
||||||
fn (p mut Parser) import_stmt() ast.Import {
|
fn (p mut Parser) import_stmt() ast.Import {
|
||||||
p.check(.key_import)
|
p.check(.key_import)
|
||||||
name := p.check_name()
|
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{
|
return ast.Import{
|
||||||
mods: [name]
|
mods: mods
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -700,14 +606,10 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
|
||||||
}
|
}
|
||||||
fields << types.Field{
|
fields << types.Field{
|
||||||
name: field_name
|
name: field_name
|
||||||
type_idx: ti.type_idx
|
type_idx: ti.idx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.check(.rcbr)
|
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{
|
p.table.register_struct(types.Struct{
|
||||||
name: name
|
name: name
|
||||||
fields: fields
|
fields: fields
|
||||||
|
@ -723,7 +625,7 @@ fn (p mut Parser) return_stmt() ast.Return {
|
||||||
p.next()
|
p.next()
|
||||||
expr,t := p.expr(0)
|
expr,t := p.expr(0)
|
||||||
if !types.check(p.return_ti, t) {
|
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{
|
return ast.Return{
|
||||||
expr: expr
|
expr: expr
|
||||||
|
@ -743,22 +645,22 @@ fn (p mut Parser) var_decl() ast.VarDecl {
|
||||||
}
|
}
|
||||||
name := p.tok.lit
|
name := p.tok.lit
|
||||||
p.read_first_token()
|
p.read_first_token()
|
||||||
expr,t := p.expr(token.lowest_prec)
|
expr,ti := p.expr(token.lowest_prec)
|
||||||
if _ := p.table.find_var(name) {
|
if _ := p.table.find_var(name) {
|
||||||
p.error('redefinition of `$name`')
|
p.error('redefinition of `$name`')
|
||||||
}
|
}
|
||||||
p.table.register_var(table.Var{
|
p.table.register_var(table.Var{
|
||||||
name: name
|
name: name
|
||||||
ti: t
|
ti: ti
|
||||||
is_mut: is_mut
|
is_mut: is_mut
|
||||||
})
|
})
|
||||||
// println(p.table.names)
|
// println(p.table.names)
|
||||||
// println('added $name')
|
// println('added var `$name` with type $t.name')
|
||||||
return ast.VarDecl{
|
return ast.VarDecl{
|
||||||
name: name
|
name: name
|
||||||
expr: expr // p.expr(token.lowest_prec)
|
expr: expr // p.expr(token.lowest_prec)
|
||||||
|
|
||||||
ti: t
|
ti: ti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
v.ast
|
v.ast
|
||||||
v.gen
|
v.gen
|
||||||
v.table
|
v.table
|
||||||
|
term
|
||||||
)
|
)
|
||||||
|
|
||||||
fn test_parse_file() {
|
fn test_parse_file() {
|
||||||
|
@ -27,23 +28,58 @@ x := 10
|
||||||
println(res)
|
println(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_parse_expr() {
|
fn test_one() {
|
||||||
input := [
|
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 := 1',
|
||||||
'q + 777',
|
'q + 777',
|
||||||
'2 + 3',
|
'2 + 3',
|
||||||
'2+2*4',
|
'2+2*4',
|
||||||
// '(2+2)*4',
|
// '(2+2)*4',
|
||||||
'x := 10',
|
'x := 10',
|
||||||
'mut a := 12',
|
'mut aa := 12',
|
||||||
'ab := 10 + 3 * 9',
|
'ab := 10 + 3 * 9',
|
||||||
's := "hi"',
|
's := "hi"',
|
||||||
// '1 += 2',
|
// '1 += 2',
|
||||||
|
'x = 11',
|
||||||
'a += 10',
|
'a += 10',
|
||||||
'1.2 + 3.4',
|
'1.2 + 3.4',
|
||||||
'4 + 4',
|
'4 + 4',
|
||||||
'1 + 2 * 5',
|
'1 + 2 * 5',
|
||||||
|
'-a',
|
||||||
|
/*
|
||||||
/*
|
/*
|
||||||
'(2 * 3) / 2',
|
'(2 * 3) / 2',
|
||||||
'3 + (7 * 6)',
|
'3 + (7 * 6)',
|
||||||
|
@ -52,28 +88,39 @@ fn test_parse_expr() {
|
||||||
'(2) + (17*2-30) * (5)+2 - (8/2)*4', // 8
|
'(2) + (17*2-30) * (5)+2 - (8/2)*4', // 8
|
||||||
//'2 + "hi"',
|
//'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;',
|
'int q = 1;',
|
||||||
'q + 777;',
|
'q + 777;',
|
||||||
'2 + 3;',
|
'2 + 3;',
|
||||||
'2 + 2 * 4;',
|
'2 + 2 * 4;',
|
||||||
// '(2 + 2) * 4',
|
// '(2 + 2) * 4',
|
||||||
'int x = 10;',
|
'int x = 10;',
|
||||||
'int a = 12;',
|
'int aa = 12;',
|
||||||
'int ab = 10 + 3 * 9;',
|
'int ab = 10 + 3 * 9;',
|
||||||
'string s = tos3("hi");',
|
'string s = tos3("hi");',
|
||||||
// '1 += 2;',
|
// '1 += 2;',
|
||||||
|
'x = 11;',
|
||||||
'a += 10;',
|
'a += 10;',
|
||||||
'1.2 + 3.4;',
|
'1.2 + 3.4;',
|
||||||
'4 + 4;',
|
'4 + 4;',
|
||||||
'1 + 2 * 5;',
|
'1 + 2 * 5;',
|
||||||
|
'-a;',
|
||||||
]
|
]
|
||||||
mut e := []ast.Stmt
|
mut e := []ast.Stmt
|
||||||
table := &table.Table{}
|
table := &table.Table{}
|
||||||
for s in input {
|
for s in input {
|
||||||
|
// println('\n\nst="$s"')
|
||||||
e << parse_stmt(s, table)
|
e << parse_stmt(s, table)
|
||||||
}
|
}
|
||||||
program := ast.File{
|
program := ast.File{
|
||||||
|
@ -89,8 +136,13 @@ fn test_parse_expr() {
|
||||||
if line == '' {
|
if line == '' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
println('V:"$line" expecting:"${expecting[i]}"')
|
if line != expecting[i] {
|
||||||
|
println('V:"$line" expecting:"${expecting[i]}"')
|
||||||
|
}
|
||||||
assert line == expecting[i]
|
assert line == expecting[i]
|
||||||
|
println(term.green('$i OK'))
|
||||||
|
println(line)
|
||||||
|
println('')
|
||||||
i++
|
i++
|
||||||
if i >= expecting.len {
|
if i >= expecting.len {
|
||||||
break
|
break
|
||||||
|
|
|
@ -8,8 +8,8 @@ import (
|
||||||
pub struct Table {
|
pub struct Table {
|
||||||
// struct_fields map[string][]string
|
// struct_fields map[string][]string
|
||||||
pub mut:
|
pub mut:
|
||||||
// types map[string]types.Type
|
|
||||||
types []types.Type
|
types []types.Type
|
||||||
|
// type_idxs Hashmap
|
||||||
type_idxs map[string]int
|
type_idxs map[string]int
|
||||||
local_vars []Var
|
local_vars []Var
|
||||||
// fns Hashmap
|
// fns Hashmap
|
||||||
|
@ -30,7 +30,7 @@ pub struct Fn {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
args []Var
|
args []Var
|
||||||
return_ti types.TypeIdent
|
return_ti types.TypeIdent
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_table() &Table {
|
pub fn new_table() &Table {
|
||||||
|
@ -46,7 +46,6 @@ pub fn new_table() &Table {
|
||||||
// save index check, 0 will mean not found
|
// save index check, 0 will mean not found
|
||||||
t.types << types.Type{}
|
t.types << types.Type{}
|
||||||
t.type_idxs['dymmy_type_at_idx_0'] = 0
|
t.type_idxs['dymmy_type_at_idx_0'] = 0
|
||||||
|
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,108 +116,6 @@ pub fn (t mut Table) register_fn(new_fn Fn) {
|
||||||
t.fns[new_fn.name] = new_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 {
|
pub fn (t mut Table) new_tmp_var() string {
|
||||||
t.tmp_cnt++
|
t.tmp_cnt++
|
||||||
|
|
|
@ -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]
|
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 {
|
pub fn (t Kind) is_assign() bool {
|
||||||
return t.kind in assign_tokens
|
return t in assign_tokens
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (t []Kind) contains(val Kind) bool {
|
fn (t []Kind) contains(val Kind) bool {
|
||||||
|
@ -308,7 +308,54 @@ pub const (
|
||||||
lowest_prec = 0
|
lowest_prec = 0
|
||||||
highest_prec = 8
|
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 {
|
pub fn (tok Token) precedence() int {
|
||||||
match tok.kind {
|
match tok.kind {
|
||||||
.dot {
|
.dot {
|
||||||
|
@ -316,6 +363,7 @@ pub fn (tok Token) precedence() int {
|
||||||
}
|
}
|
||||||
// `++` | `--`
|
// `++` | `--`
|
||||||
.inc, .dec {
|
.inc, .dec {
|
||||||
|
// return 0
|
||||||
return 7
|
return 7
|
||||||
}
|
}
|
||||||
// `*` | `/` | `%` | `<<` | `>>` | `&`
|
// `*` | `/` | `%` | `<<` | `>>` | `&`
|
||||||
|
@ -335,7 +383,7 @@ pub fn (tok Token) precedence() int {
|
||||||
return 3
|
return 3
|
||||||
}
|
}
|
||||||
// `||`
|
// `||`
|
||||||
.logical_or {
|
.logical_or, .assign, .plus_assign, .minus_assign, .div_assign, .mult_assign {
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
// /.plus_assign {
|
// /.plus_assign {
|
||||||
|
@ -396,8 +444,12 @@ pub fn (tok Token) is_right_assoc() bool {
|
||||||
.and_assign, .xor_assign, .or_assign]
|
.and_assign, .xor_assign, .or_assign]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (tok Token) is_relational() bool {
|
pub fn (tok Kind) is_relational() bool {
|
||||||
return tok.kind in [
|
return tok in [
|
||||||
// `<` | `<=` | `>` | `>=`
|
// `<` | `<=` | `>` | `>=`
|
||||||
.lt, .le, .gt, .ge, .eq, .ne]
|
.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 struct TypeIdent {
|
||||||
pub:
|
pub:
|
||||||
type_idx int
|
idx int
|
||||||
type_kind Kind
|
kind Kind
|
||||||
type_name string
|
name string
|
||||||
nr_muls int
|
nr_muls int
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[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{
|
return TypeIdent{
|
||||||
type_idx: type_idx
|
idx: idx
|
||||||
type_kind: type_kind
|
kind: kind
|
||||||
type_name: type_name
|
name: name
|
||||||
nr_muls: nr_muls
|
nr_muls: nr_muls
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[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{
|
return TypeIdent{
|
||||||
type_kind: type_kind
|
kind: kind
|
||||||
type_name: type_kind.str()
|
name: kind.str()
|
||||||
nr_muls: nr_muls
|
nr_muls: nr_muls
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,12 +66,12 @@ pub fn (ti &TypeIdent) is_ptr() bool {
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (ti &TypeIdent) is_int() bool {
|
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]
|
[inline]
|
||||||
pub fn (ti &TypeIdent) is_float() bool {
|
pub fn (ti &TypeIdent) is_float() bool {
|
||||||
return ti.type_kind in [._f32, ._f64]
|
return ti.kind in [._f32, ._f64]
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
@ -80,18 +80,18 @@ pub fn (ti &TypeIdent) is_number() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (ti &TypeIdent) str() string {
|
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 {
|
pub fn check(got, expected &TypeIdent) bool {
|
||||||
if got.type_idx != expected.type_idx {
|
if got.idx != expected.idx {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (t Kind) str() string {
|
pub fn (k Kind) str() string {
|
||||||
t_str := match t {
|
k_str := match k {
|
||||||
._placeholder {
|
._placeholder {
|
||||||
'placeholder'
|
'placeholder'
|
||||||
}
|
}
|
||||||
|
@ -168,7 +168,18 @@ pub fn (t Kind) str() string {
|
||||||
'unknown'
|
'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 |
|
pub type Type = Placeholder | Void | Voidptr | Charptr | Byteptr | Const | Enum | Struct |
|
||||||
|
@ -179,7 +190,7 @@ pub struct Placeholder {
|
||||||
pub:
|
pub:
|
||||||
idx int
|
idx int
|
||||||
name string
|
name string
|
||||||
kind Kind
|
// kind Kind
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Void {}
|
pub struct Void {}
|
||||||
|
@ -250,6 +261,7 @@ pub:
|
||||||
elem_type_kind Kind
|
elem_type_kind Kind
|
||||||
elem_type_idx int
|
elem_type_idx int
|
||||||
elem_is_ptr bool
|
elem_is_ptr bool
|
||||||
|
nr_dims int
|
||||||
size int
|
size int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,14 +277,17 @@ pub:
|
||||||
|
|
||||||
pub struct MultiReturn {
|
pub struct MultiReturn {
|
||||||
pub:
|
pub:
|
||||||
elem_type_kinds []Kind
|
idx int
|
||||||
elem_type_idxs []int
|
name string
|
||||||
|
type_kinds []Kind
|
||||||
|
type_idxs []int
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Variadic {
|
pub struct Variadic {
|
||||||
pub:
|
pub:
|
||||||
elem_type_kind Kind
|
idx int
|
||||||
elem_type_idx int
|
type_kind Kind
|
||||||
|
type_idx int
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (t Void) str() string { return 'void' }
|
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 Array) str() string { return t.name }
|
||||||
pub fn (t ArrayFixed) 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 Map) str() string { return t.name }
|
||||||
pub fn (t MultiReturn) str() string { return 'multi_return_$t.elem_type_kinds.str()' }
|
pub fn (t MultiReturn) str() string { return t.name }
|
||||||
pub fn (t Variadic) str() string { return 'variadic_$t.elem_type_kind.str()' }
|
pub fn (t Variadic) str() string { return 'variadic_$t.type_kind.str()' }
|
||||||
|
|
||||||
pub const (
|
pub const (
|
||||||
void_type = Void{}
|
void_type = Void{}
|
||||||
|
@ -312,3 +327,10 @@ pub const (
|
||||||
char_type = Char{}
|
char_type = Char{}
|
||||||
bool_type = Bool{}
|
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