mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
ast: return types, variable declaration
This commit is contained in:
parent
320174bd5b
commit
0a3adb5de8
@ -4,8 +4,9 @@
|
|||||||
module compiler
|
module compiler
|
||||||
|
|
||||||
fn (p mut Parser) bool_expression() string {
|
fn (p mut Parser) bool_expression() string {
|
||||||
|
is_ret := p.prev_tok == .key_return
|
||||||
start_ph := p.cgen.add_placeholder()
|
start_ph := p.cgen.add_placeholder()
|
||||||
expected := p.expected_type
|
mut expected := p.expected_type
|
||||||
tok := p.tok
|
tok := p.tok
|
||||||
typ := p.bterm()
|
typ := p.bterm()
|
||||||
mut got_and := false // to catch `a && b || c` in one expression without ()
|
mut got_and := false // to catch `a && b || c` in one expression without ()
|
||||||
@ -46,7 +47,11 @@ fn (p mut Parser) bool_expression() string {
|
|||||||
println(tok.str())
|
println(tok.str())
|
||||||
p.error('expr() returns empty type')
|
p.error('expr() returns empty type')
|
||||||
}
|
}
|
||||||
|
if p.inside_return_expr { //is_ret { // return a,b hack TODO
|
||||||
|
expected = p.expected_type
|
||||||
|
}
|
||||||
if expected != typ && expected in p.table.sum_types { // TODO perf
|
if expected != typ && expected in p.table.sum_types { // TODO perf
|
||||||
|
//p.warn('SUM CAST exp=$expected typ=$typ p.exp=$p.expected_type')
|
||||||
p.cgen.set_placeholder(start_ph,
|
p.cgen.set_placeholder(start_ph,
|
||||||
//'/*SUM TYPE CAST*/($expected) { .obj = &($typ[]) { ')
|
//'/*SUM TYPE CAST*/($expected) { .obj = &($typ[]) { ')
|
||||||
'/*SUM TYPE CAST*/($expected) { .obj = memdup(& ')
|
'/*SUM TYPE CAST*/($expected) { .obj = memdup(& ')
|
||||||
|
@ -272,8 +272,9 @@ fn (p &Parser) gen_fmt() {
|
|||||||
s3 := s2.replace(') or{', ') or {')
|
s3 := s2.replace(') or{', ') or {')
|
||||||
s4 := s3.replace(')or{', ') or {')
|
s4 := s3.replace(')or{', ') or {')
|
||||||
s5 := s4.replace('or{', 'or {')
|
s5 := s4.replace('or{', 'or {')
|
||||||
|
s6 := s5.replace('}}\n', '}\n\t}\n')
|
||||||
|
|
||||||
s := s5
|
s := s6
|
||||||
|
|
||||||
if s == '' {
|
if s == '' {
|
||||||
return
|
return
|
||||||
|
@ -11,8 +11,9 @@ import (
|
|||||||
struct Foo {}
|
struct Foo {}
|
||||||
|
|
||||||
pub type Expr = Foo | IfExpr | BinaryExpr | UnaryExpr |
|
pub type Expr = Foo | IfExpr | BinaryExpr | UnaryExpr |
|
||||||
StringLiteral | IntegerLiteral
|
StringLiteral | IntegerLiteral | VarDecl
|
||||||
pub type Stmt = Foo | VarDecl
|
|
||||||
|
pub type Stmt = Foo | Foo //VarDecl
|
||||||
|
|
||||||
pub struct IntegerLiteral {
|
pub struct IntegerLiteral {
|
||||||
pub:
|
pub:
|
||||||
@ -43,6 +44,7 @@ pub struct VarDecl {
|
|||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
expr Expr
|
expr Expr
|
||||||
|
typ Type
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,6 +53,18 @@ pub:
|
|||||||
exprs []Expr
|
exprs []Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Type {
|
||||||
|
pub:
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const (
|
||||||
|
string_type = Type{'string'}
|
||||||
|
int_type = Type{'int'}
|
||||||
|
void_type = Type{'void'}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
// A single identifier
|
// A single identifier
|
||||||
struct Ident {
|
struct Ident {
|
||||||
token token.Token
|
token token.Token
|
||||||
@ -63,7 +77,9 @@ pub:
|
|||||||
//op BinaryOp
|
//op BinaryOp
|
||||||
op token.Token
|
op token.Token
|
||||||
left Expr
|
left Expr
|
||||||
|
left_type Type
|
||||||
right Expr
|
right Expr
|
||||||
|
right_type Type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UnaryExpr {
|
pub struct UnaryExpr {
|
||||||
@ -90,13 +106,16 @@ struct ReturnStmt {
|
|||||||
pub fn (x Expr) str() string {
|
pub fn (x Expr) str() string {
|
||||||
match x {
|
match x {
|
||||||
BinaryExpr {
|
BinaryExpr {
|
||||||
return '(${it.left.str()}$it.op.str()${it.right.str()})'
|
return '(${it.left.str()} $it.op.str() ${it.right.str()})'
|
||||||
}
|
}
|
||||||
//ScalarExpr {
|
|
||||||
//return '${it.left.str()}$it.val'
|
|
||||||
//}
|
|
||||||
UnaryExpr {
|
UnaryExpr {
|
||||||
return '${it.left.str()}$it.op.str()'
|
return it.left.str() + it.op.str()
|
||||||
|
}
|
||||||
|
IntegerLiteral {
|
||||||
|
return it.val.str()
|
||||||
|
}
|
||||||
|
IntegerLiteral {
|
||||||
|
return '"$it.val"'
|
||||||
}
|
}
|
||||||
else { return '' }
|
else { return '' }
|
||||||
}
|
}
|
||||||
|
@ -41,12 +41,11 @@ const (
|
|||||||
void_type = Type{'void'}
|
void_type = Type{'void'}
|
||||||
)
|
)
|
||||||
|
|
||||||
fn (g mut Gen) expr(node ast.Expr) Type {
|
fn (g mut Gen) expr(node ast.Expr) {
|
||||||
//println('cgen expr()')
|
//println('cgen expr()')
|
||||||
match node {
|
match node {
|
||||||
ast.IntegerLiteral {
|
ast.IntegerLiteral {
|
||||||
g.write(it.val.str())
|
g.write(it.val.str())
|
||||||
return int_type
|
|
||||||
}
|
}
|
||||||
ast.UnaryExpr {
|
ast.UnaryExpr {
|
||||||
g.expr(it.left)
|
g.expr(it.left)
|
||||||
@ -54,10 +53,9 @@ fn (g mut Gen) expr(node ast.Expr) Type {
|
|||||||
}
|
}
|
||||||
ast.StringLiteral {
|
ast.StringLiteral {
|
||||||
g.write('"$it.val"')
|
g.write('"$it.val"')
|
||||||
return string_type
|
|
||||||
}
|
}
|
||||||
ast.BinaryExpr {
|
ast.BinaryExpr {
|
||||||
typ := g.expr(it.left)
|
g.expr(it.left)
|
||||||
match it.op {
|
match it.op {
|
||||||
.plus { g.write(' + ') }
|
.plus { g.write(' + ') }
|
||||||
.minus { g.write(' - ') }
|
.minus { g.write(' - ') }
|
||||||
@ -65,22 +63,24 @@ fn (g mut Gen) expr(node ast.Expr) Type {
|
|||||||
.div { g.write(' / ') }
|
.div { g.write(' / ') }
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
typ2 := g.expr(it.right)
|
g.expr(it.right)
|
||||||
if typ.name != typ2.name {
|
// if typ.name != typ2.name {
|
||||||
println('bad types $typ.name $typ2.name')
|
//verror('bad types $typ.name $typ2.name')
|
||||||
}
|
//}
|
||||||
return typ
|
|
||||||
}
|
}
|
||||||
ast.VarDecl {
|
ast.VarDecl {
|
||||||
g.write('var $it.name = ')
|
g.write('$it.typ.name $it.name = ')
|
||||||
g.expr(it.expr)
|
g.expr(it.expr)
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
return void_type
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
println('bad node')
|
println('bad node')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return void_type
|
}
|
||||||
|
|
||||||
|
fn verror(s string) {
|
||||||
|
println(s)
|
||||||
|
exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
compiler2.scanner
|
compiler2.scanner
|
||||||
compiler2.ast
|
compiler2.ast
|
||||||
compiler2.token
|
compiler2.token
|
||||||
|
compiler2.table
|
||||||
)
|
)
|
||||||
|
|
||||||
struct Parser {
|
struct Parser {
|
||||||
@ -14,20 +15,49 @@ struct Parser {
|
|||||||
mut:
|
mut:
|
||||||
tok token.Token
|
tok token.Token
|
||||||
lit string
|
lit string
|
||||||
|
//vars []string
|
||||||
|
table &table.Table
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_expr(text string) ast.Expr {
|
pub fn parse_expr(text string, table &table.Table) ast.Expr {
|
||||||
mut s := scanner.new_scanner(text)
|
mut s := scanner.new_scanner(text)
|
||||||
res := s.scan()
|
res := s.scan()
|
||||||
mut p := Parser{
|
mut p := Parser{
|
||||||
scanner: s
|
scanner: s
|
||||||
tok: res.tok
|
tok: res.tok
|
||||||
lit: res.lit
|
lit: res.lit
|
||||||
|
table: table
|
||||||
}
|
}
|
||||||
// return p.expr()
|
expr,_ := p.expr(token.lowest_prec)
|
||||||
return p.expr(token.lowest_prec)
|
return expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_file(text string, table &table.Table) ast.Program {
|
||||||
|
s := scanner.new_scanner(text)
|
||||||
|
mut exprs := []ast.Expr
|
||||||
|
mut p := Parser{
|
||||||
|
scanner: s
|
||||||
|
//tok: res.tok
|
||||||
|
//lit: res.lit
|
||||||
|
table: table
|
||||||
|
}
|
||||||
|
p.next()
|
||||||
|
for {
|
||||||
|
//res := s.scan()
|
||||||
|
if p.tok == .eof {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
println('expr at ' + p.tok.str())
|
||||||
|
expr,_ := p.expr(token.lowest_prec)
|
||||||
|
exprs << expr
|
||||||
|
p.next()
|
||||||
|
}
|
||||||
|
println('nr exprs = $exprs.len')
|
||||||
|
println(exprs[0])
|
||||||
|
return ast.Program{exprs}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
pub fn parse_stmt(text string) ast.Stmt {
|
pub fn parse_stmt(text string) ast.Stmt {
|
||||||
mut s := scanner.new_scanner(text)
|
mut s := scanner.new_scanner(text)
|
||||||
res := s.scan()
|
res := s.scan()
|
||||||
@ -38,6 +68,8 @@ pub fn parse_stmt(text string) ast.Stmt {
|
|||||||
}
|
}
|
||||||
return p.stmt()
|
return p.stmt()
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
fn (p mut Parser) next() {
|
fn (p mut Parser) next() {
|
||||||
res := p.scanner.scan()
|
res := p.scanner.scan()
|
||||||
@ -47,15 +79,40 @@ fn (p mut Parser) next() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implementation of Pratt Precedence
|
// Implementation of Pratt Precedence
|
||||||
pub fn (p mut Parser) expr(rbp int) ast.Expr {
|
pub fn (p mut Parser) expr(rbp int) (ast.Expr,ast.Type) {
|
||||||
// null denotation (prefix)
|
// null denotation (prefix)
|
||||||
tok := p.tok
|
tok := p.tok
|
||||||
lit := p.lit
|
lit := p.lit
|
||||||
p.next()
|
|
||||||
|
if p.tok == .name {
|
||||||
|
name := p.lit
|
||||||
|
p.next()
|
||||||
|
if p.tok == .decl_assign {
|
||||||
|
p.next()
|
||||||
|
mut node := ast.Expr{}
|
||||||
|
expr,t :=p.expr(token.lowest_prec)
|
||||||
|
if name in p.table.names {
|
||||||
|
verror('redefinition of `$name`')
|
||||||
|
}
|
||||||
|
p.table.names << name
|
||||||
|
println(p.table.names)
|
||||||
|
println('added $name')
|
||||||
|
// TODO can't return VarDecl{}
|
||||||
|
node = ast.VarDecl{
|
||||||
|
name: name
|
||||||
|
expr: expr//p.expr(token.lowest_prec)
|
||||||
|
typ: t
|
||||||
|
}//, ast.void_type
|
||||||
|
return node, ast.void_type
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p.next()
|
||||||
|
}
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
|
mut typ := ast.void_type
|
||||||
match tok {
|
match tok {
|
||||||
.lpar {
|
.lpar {
|
||||||
node = p.expr(0)
|
node,typ = p.expr(0)
|
||||||
if p.tok != .rpar {
|
if p.tok != .rpar {
|
||||||
panic('Parse Error: expected )')
|
panic('Parse Error: expected )')
|
||||||
}
|
}
|
||||||
@ -65,48 +122,70 @@ pub fn (p mut Parser) expr(rbp int) ast.Expr {
|
|||||||
// TODO: fix bug. note odd conditon instead of else if (same below)
|
// TODO: fix bug. note odd conditon instead of else if (same below)
|
||||||
if tok.is_scalar() {
|
if tok.is_scalar() {
|
||||||
if tok == .str {
|
if tok == .str {
|
||||||
node = ast.StringLiteral {
|
node = ast.StringLiteral{
|
||||||
val: lit
|
val: lit
|
||||||
}
|
}
|
||||||
} if tok == .number {
|
typ = ast.string_type
|
||||||
node = ast.IntegerLiteral {
|
}
|
||||||
|
if tok == .number {
|
||||||
|
node = ast.IntegerLiteral{
|
||||||
val: lit.int()
|
val: lit.int()
|
||||||
}
|
}
|
||||||
|
typ = ast.int_type
|
||||||
}
|
}
|
||||||
//else {
|
// else {
|
||||||
//verror('bad scalar token')
|
// verror('bad scalar token')
|
||||||
//}
|
// }
|
||||||
}
|
}
|
||||||
if !tok.is_scalar() && tok.is_unary() {
|
if !tok.is_scalar() && tok.is_unary() {
|
||||||
|
expr,_ := p.expr(token.highest_prec)
|
||||||
node = ast.UnaryExpr{
|
node = ast.UnaryExpr{
|
||||||
left: p.expr(token.highest_prec)
|
// left: p.expr(token.highest_prec)
|
||||||
|
left: expr
|
||||||
op: tok
|
op: tok
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}
|
||||||
|
}
|
||||||
// left binding power
|
// left binding power
|
||||||
for rbp < p.tok.precedence() {
|
for rbp < p.tok.precedence() {
|
||||||
tok2 := p.tok
|
tok2 := p.tok
|
||||||
p.next()
|
p.next()
|
||||||
|
//mut t1 := ast.Type{}
|
||||||
|
mut t2 := ast.Type{}
|
||||||
|
//mut q := false
|
||||||
// left denotation (infix)
|
// left denotation (infix)
|
||||||
if tok2.is_right_assoc() {
|
if tok2.is_right_assoc() {
|
||||||
|
//q = true
|
||||||
|
mut expr := ast.Expr{}
|
||||||
|
expr,t2 = p.expr(tok2.precedence() - 1)
|
||||||
node = ast.BinaryExpr{
|
node = ast.BinaryExpr{
|
||||||
left: node
|
left: node
|
||||||
|
//left_type: t1
|
||||||
op: tok2
|
op: tok2
|
||||||
right: p.expr(tok2.precedence() - 1)
|
// right: p.expr(tok2.precedence() - 1)
|
||||||
|
|
||||||
|
right: expr
|
||||||
|
|
||||||
|
}
|
||||||
|
if typ.name != t2.name {
|
||||||
|
println('bad types $typ.name $t2.name')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !tok2.is_right_assoc() && tok2.is_left_assoc() {
|
if !tok2.is_right_assoc() && tok2.is_left_assoc() {
|
||||||
|
mut expr := ast.Expr{}
|
||||||
|
expr,t2 = p.expr(tok2.precedence())
|
||||||
node = ast.BinaryExpr{
|
node = ast.BinaryExpr{
|
||||||
left: node
|
left: node
|
||||||
op: tok2
|
op: tok2
|
||||||
right: p.expr(tok2.precedence())
|
right: expr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return node
|
return node,typ
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
fn (p mut Parser) stmt() ast.Stmt {
|
fn (p mut Parser) stmt() ast.Stmt {
|
||||||
if p.tok == .name {
|
if p.tok == .name {
|
||||||
name := p.lit
|
name := p.lit
|
||||||
@ -131,6 +210,8 @@ fn (p mut Parser) stmt() ast.Stmt {
|
|||||||
|
|
||||||
return ast.VarDecl{}
|
return ast.VarDecl{}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
fn verror(s string) {
|
fn verror(s string) {
|
||||||
println(s)
|
println(s)
|
||||||
|
@ -3,6 +3,8 @@ module parser
|
|||||||
import (
|
import (
|
||||||
compiler2.ast
|
compiler2.ast
|
||||||
compiler2.cgen
|
compiler2.cgen
|
||||||
|
compiler2.table
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
fn test_parser() {
|
fn test_parser() {
|
||||||
@ -11,8 +13,8 @@ fn test_parser() {
|
|||||||
//expr := ast.BinaryExpr{}
|
//expr := ast.BinaryExpr{}
|
||||||
|
|
||||||
// print using walk
|
// print using walk
|
||||||
expr := parse_expr('3 + 7')
|
//expr := parse_expr('3 + 7')
|
||||||
println('\n')
|
//println('\n')
|
||||||
|
|
||||||
text_expr := [
|
text_expr := [
|
||||||
'1 += 2',
|
'1 += 2',
|
||||||
@ -24,29 +26,53 @@ fn test_parser() {
|
|||||||
'2 ^ 8 * (7 * 6)',
|
'2 ^ 8 * (7 * 6)',
|
||||||
'20 + (10 * 15) / 5', // 50
|
'20 + (10 * 15) / 5', // 50
|
||||||
'(2) + (17*2-30) * (5)+2 - (8/2)*4', // 8
|
'(2) + (17*2-30) * (5)+2 - (8/2)*4', // 8
|
||||||
'2 + "hi"'
|
'2 + "hi"',
|
||||||
|
'x := 10'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
table := &table.Table{}
|
||||||
for s in text_expr {
|
for s in text_expr {
|
||||||
// print using str method
|
// print using str method
|
||||||
x := parse_expr(s)
|
x := parse_expr(s, table)
|
||||||
println('source: $s')
|
println('source: $s')
|
||||||
println('parsed: $x')
|
println('parsed: $x')
|
||||||
println('===================')
|
println('===================')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
fn test_cgen2() {
|
||||||
|
s := '2 + 3
|
||||||
|
5+7
|
||||||
|
//x := 100
|
||||||
|
'
|
||||||
|
table := &table.Table{}
|
||||||
|
prog := parse_file(s, table)
|
||||||
|
cgen.gen(prog)
|
||||||
|
println('done')
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
fn test_cgen() {
|
fn test_cgen() {
|
||||||
|
//if true { return }
|
||||||
|
s := [
|
||||||
|
'x := 10',
|
||||||
|
//'x := 10'
|
||||||
|
]
|
||||||
//expr := parse_expr('3 + 7 * 2')
|
//expr := parse_expr('3 + 7 * 2')
|
||||||
//expr2 := parse_stmt('a := 3 + "f"')
|
//expr2 := parse_stmt('a := 3 + "f"')
|
||||||
expr2 := parse_expr('2 + "helo"')
|
mut e := []ast.Expr
|
||||||
program := ast.Program{
|
table := &table.Table{}
|
||||||
exprs: [
|
for ss in s {
|
||||||
expr2,
|
//expr2 := parse_expr('x := 10')
|
||||||
|
//program := ast.Program{
|
||||||
|
e << parse_expr(ss, table)
|
||||||
|
//exprs: [
|
||||||
|
//expr2,
|
||||||
//parse_expr('2 * 2'),
|
//parse_expr('2 * 2'),
|
||||||
]
|
//]
|
||||||
}
|
}
|
||||||
|
program := ast.Program{exprs:e}
|
||||||
cgen.gen(program)
|
cgen.gen(program)
|
||||||
//cgen.save()
|
//cgen.save()
|
||||||
}
|
}
|
||||||
|
7
vlib/compiler2/table/table.v
Normal file
7
vlib/compiler2/table/table.v
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module table
|
||||||
|
|
||||||
|
pub struct Table {
|
||||||
|
pub mut:
|
||||||
|
names []string
|
||||||
|
|
||||||
|
}
|
@ -289,7 +289,7 @@ fn (t []Token) contains(val Token) bool {
|
|||||||
pub fn (t Token) str() string {
|
pub fn (t Token) str() string {
|
||||||
lit := 't.lit'
|
lit := 't.lit'
|
||||||
if t == .number {
|
if t == .number {
|
||||||
return lit
|
return 'number'
|
||||||
}
|
}
|
||||||
if t == .chartoken {
|
if t == .chartoken {
|
||||||
return '`lit`'
|
return '`lit`'
|
||||||
|
Loading…
Reference in New Issue
Block a user