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
|
||||
|
||||
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(& ')
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
@ -90,13 +106,16 @@ struct ReturnStmt {
|
||||
pub fn (x Expr) str() string {
|
||||
match x {
|
||||
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 {
|
||||
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 '' }
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
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 typ := ast.void_type
|
||||
match tok {
|
||||
.lpar {
|
||||
node = p.expr(0)
|
||||
node,typ = p.expr(0)
|
||||
if p.tok != .rpar {
|
||||
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)
|
||||
if tok.is_scalar() {
|
||||
if tok == .str {
|
||||
node = ast.StringLiteral {
|
||||
node = ast.StringLiteral{
|
||||
val: lit
|
||||
}
|
||||
} if tok == .number {
|
||||
node = ast.IntegerLiteral {
|
||||
typ = ast.string_type
|
||||
}
|
||||
if tok == .number {
|
||||
node = ast.IntegerLiteral{
|
||||
val: lit.int()
|
||||
}
|
||||
typ = ast.int_type
|
||||
}
|
||||
//else {
|
||||
//verror('bad scalar token')
|
||||
//}
|
||||
// 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)
|
||||
|
@ -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()
|
||||
}
|
||||
|
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 {
|
||||
lit := 't.lit'
|
||||
if t == .number {
|
||||
return lit
|
||||
return 'number'
|
||||
}
|
||||
if t == .chartoken {
|
||||
return '`lit`'
|
||||
|
Loading…
Reference in New Issue
Block a user