1
0
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:
Alexander Medvednikov 2019-12-26 13:27:35 +03:00
parent 320174bd5b
commit 0a3adb5de8
8 changed files with 187 additions and 48 deletions

View File

@ -4,8 +4,9 @@
module compiler
fn (p mut Parser) bool_expression() string {
is_ret := p.prev_tok == .key_return
start_ph := p.cgen.add_placeholder()
expected := p.expected_type
mut expected := p.expected_type
tok := p.tok
typ := p.bterm()
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())
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
//p.warn('SUM CAST exp=$expected typ=$typ p.exp=$p.expected_type')
p.cgen.set_placeholder(start_ph,
//'/*SUM TYPE CAST*/($expected) { .obj = &($typ[]) { ')
'/*SUM TYPE CAST*/($expected) { .obj = memdup(& ')

View File

@ -272,8 +272,9 @@ fn (p &Parser) gen_fmt() {
s3 := s2.replace(') or{', ') or {')
s4 := s3.replace(')or{', ') or {')
s5 := s4.replace('or{', 'or {')
s6 := s5.replace('}}\n', '}\n\t}\n')
s := s5
s := s6
if s == '' {
return

View File

@ -11,8 +11,9 @@ import (
struct Foo {}
pub type Expr = Foo | IfExpr | BinaryExpr | UnaryExpr |
StringLiteral | IntegerLiteral
pub type Stmt = Foo | VarDecl
StringLiteral | IntegerLiteral | VarDecl
pub type Stmt = Foo | Foo //VarDecl
pub struct IntegerLiteral {
pub:
@ -43,6 +44,7 @@ pub struct VarDecl {
pub:
name string
expr Expr
typ Type
}
@ -51,6 +53,18 @@ pub:
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
struct Ident {
token token.Token
@ -63,7 +77,9 @@ pub:
//op BinaryOp
op token.Token
left Expr
left_type Type
right Expr
right_type Type
}
pub struct UnaryExpr {
@ -92,11 +108,14 @@ pub fn (x Expr) str() string {
BinaryExpr {
return '(${it.left.str()} $it.op.str() ${it.right.str()})'
}
//ScalarExpr {
//return '${it.left.str()}$it.val'
//}
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 '' }
}

View File

@ -41,12 +41,11 @@ const (
void_type = Type{'void'}
)
fn (g mut Gen) expr(node ast.Expr) Type {
fn (g mut Gen) expr(node ast.Expr) {
//println('cgen expr()')
match node {
ast.IntegerLiteral {
g.write(it.val.str())
return int_type
}
ast.UnaryExpr {
g.expr(it.left)
@ -54,10 +53,9 @@ fn (g mut Gen) expr(node ast.Expr) Type {
}
ast.StringLiteral {
g.write('"$it.val"')
return string_type
}
ast.BinaryExpr {
typ := g.expr(it.left)
g.expr(it.left)
match it.op {
.plus { g.write(' + ') }
.minus { g.write(' - ') }
@ -65,22 +63,24 @@ fn (g mut Gen) expr(node ast.Expr) Type {
.div { g.write(' / ') }
else {}
}
typ2 := g.expr(it.right)
if typ.name != typ2.name {
println('bad types $typ.name $typ2.name')
}
return typ
g.expr(it.right)
// if typ.name != typ2.name {
//verror('bad types $typ.name $typ2.name')
//}
}
ast.VarDecl {
g.write('var $it.name = ')
g.write('$it.typ.name $it.name = ')
g.expr(it.expr)
g.writeln(';')
return void_type
}
else {
println('bad node')
}
}
return void_type
}
fn verror(s string) {
println(s)
exit(1)
}

View File

@ -7,6 +7,7 @@ import (
compiler2.scanner
compiler2.ast
compiler2.token
compiler2.table
)
struct Parser {
@ -14,20 +15,49 @@ struct Parser {
mut:
tok token.Token
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)
res := s.scan()
mut p := Parser{
scanner: s
tok: res.tok
lit: res.lit
table: table
}
// return p.expr()
return p.expr(token.lowest_prec)
expr,_ := 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 {
mut s := scanner.new_scanner(text)
res := s.scan()
@ -38,6 +68,8 @@ pub fn parse_stmt(text string) ast.Stmt {
}
return p.stmt()
}
*/
fn (p mut Parser) next() {
res := p.scanner.scan()
@ -47,15 +79,40 @@ fn (p mut Parser) next() {
}
// 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)
tok := p.tok
lit := p.lit
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 typ := ast.void_type
match tok {
.lpar {
node = p.expr(0)
node,typ = p.expr(0)
if p.tok != .rpar {
panic('Parse Error: expected )')
}
@ -68,45 +125,67 @@ pub fn (p mut Parser) expr(rbp int) ast.Expr {
node = ast.StringLiteral{
val: lit
}
} if tok == .number {
typ = ast.string_type
}
if tok == .number {
node = ast.IntegerLiteral{
val: lit.int()
}
typ = ast.int_type
}
// else {
// verror('bad scalar token')
// }
}
if !tok.is_scalar() && tok.is_unary() {
expr,_ := p.expr(token.highest_prec)
node = ast.UnaryExpr{
left: p.expr(token.highest_prec)
// left: p.expr(token.highest_prec)
left: expr
op: tok
}
}
}}
}
}
// left binding power
for rbp < p.tok.precedence() {
tok2 := p.tok
p.next()
//mut t1 := ast.Type{}
mut t2 := ast.Type{}
//mut q := false
// left denotation (infix)
if tok2.is_right_assoc() {
//q = true
mut expr := ast.Expr{}
expr,t2 = p.expr(tok2.precedence() - 1)
node = ast.BinaryExpr{
left: node
//left_type: t1
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() {
mut expr := ast.Expr{}
expr,t2 = p.expr(tok2.precedence())
node = ast.BinaryExpr{
left: node
op: tok2
right: p.expr(tok2.precedence())
right: expr
}
}
}
return node
return node,typ
}
/*
fn (p mut Parser) stmt() ast.Stmt {
if p.tok == .name {
name := p.lit
@ -131,6 +210,8 @@ fn (p mut Parser) stmt() ast.Stmt {
return ast.VarDecl{}
}
*/
fn verror(s string) {
println(s)

View File

@ -3,6 +3,8 @@ module parser
import (
compiler2.ast
compiler2.cgen
compiler2.table
)
fn test_parser() {
@ -11,8 +13,8 @@ fn test_parser() {
//expr := ast.BinaryExpr{}
// print using walk
expr := parse_expr('3 + 7')
println('\n')
//expr := parse_expr('3 + 7')
//println('\n')
text_expr := [
'1 += 2',
@ -24,29 +26,53 @@ fn test_parser() {
'2 ^ 8 * (7 * 6)',
'20 + (10 * 15) / 5', // 50
'(2) + (17*2-30) * (5)+2 - (8/2)*4', // 8
'2 + "hi"'
'2 + "hi"',
'x := 10'
]
table := &table.Table{}
for s in text_expr {
// print using str method
x := parse_expr(s)
x := parse_expr(s, table)
println('source: $s')
println('parsed: $x')
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() {
//if true { return }
s := [
'x := 10',
//'x := 10'
]
//expr := parse_expr('3 + 7 * 2')
//expr2 := parse_stmt('a := 3 + "f"')
expr2 := parse_expr('2 + "helo"')
program := ast.Program{
exprs: [
expr2,
mut e := []ast.Expr
table := &table.Table{}
for ss in s {
//expr2 := parse_expr('x := 10')
//program := ast.Program{
e << parse_expr(ss, table)
//exprs: [
//expr2,
//parse_expr('2 * 2'),
]
//]
}
program := ast.Program{exprs:e}
cgen.gen(program)
//cgen.save()
}

View File

@ -0,0 +1,7 @@
module table
pub struct Table {
pub mut:
names []string
}

View File

@ -289,7 +289,7 @@ fn (t []Token) contains(val Token) bool {
pub fn (t Token) str() string {
lit := 't.lit'
if t == .number {
return lit
return 'number'
}
if t == .chartoken {
return '`lit`'