FnDecl, Return, statement block

pull/3237/head
Alexander Medvednikov 2019-12-27 13:57:49 +01:00
parent 6c16bac908
commit 66a07d7fe0
7 changed files with 170 additions and 54 deletions

View File

@ -793,13 +793,13 @@ fn (p mut Parser) type_decl() {
if p.tok == .key_struct {
p.error('use `struct $name {` instead of `type $name struct {`')
}
if p.tok == .assign {
is_sum := p.tok == .assign
if is_sum {
p.next()
}
parent := p.get_type2()
mut parent := Type{}
// Sum type
is_sum := p.tok == .pipe
//is_sum := p.tok == .pipe
if is_sum {
if !p.builtin_mod && p.mod != 'main' {
name = p.prepend_mod(name)
@ -815,10 +815,15 @@ fn (p mut Parser) type_decl() {
*/
// Register the rest of them
mut idx := 0
for p.tok == .pipe {
mut done := false
for {//p.tok == .pipe {
idx++
p.next()
//p.next()
child_type_name := p.check_name()
//println('$idx $child_type_name')
if p.tok != .pipe {
done = true
}
if p.pass == .main {
// Update the type's parent
//println('child=$child_type_name parent=$name')
@ -830,13 +835,17 @@ fn (p mut Parser) type_decl() {
p.table.rewrite_type(t)
p.cgen.consts << '#define SumType_$child_type_name $idx // DEF2'
}
if done {
break
}
p.check(.pipe)
}
if p.pass == .decl {
p.table.sum_types << name
println(p.table.sum_types)
}
// Register the actual sum type
//println('registering sum $name')
println('registering sum $name')
p.table.register_type(Type{
name: name
mod: p.mod
@ -849,6 +858,10 @@ int typ;
} $name;
')
}
else {
parent = p.get_type2()
}
nt_pair := p.table.cgen_name_type_pair(name, parent.name)
// TODO dirty C typedef hacks for DOOM
// Unknown type probably means it's a struct, and it's used before the struct is defined,

View File

@ -11,10 +11,12 @@ import (
struct Foo {}
pub type Expr = Foo | IfExpr | BinaryExpr | UnaryExpr |
StringLiteral | IntegerLiteral | FloatLiteral | VarDecl
pub type Expr = BinaryExpr | UnaryExpr | IfExpr |
StringLiteral | IntegerLiteral | FloatLiteral | VarDecl |
FnDecl | Return
pub type Stmt = Foo//VarDecl
pub type Stmt = Foo | Foo //VarDecl
pub struct IntegerLiteral {
pub:
@ -32,6 +34,20 @@ pub:
val string
}
pub struct FnDecl {
pub:
name string
//stmts []Stmt
exprs []Expr
typ types.Type
}
pub struct Return {
pub:
expr Expr
}
/*
pub enum Expr {
Binary(BinaryExpr)

View File

@ -31,16 +31,6 @@ pub fn (g mut Gen) writeln(s string) {
g.out.writeln(s)
}
struct Type {
name string
}
const (
string_type = Type{'string'}
int_type = Type{'int'}
void_type = Type{'void'}
)
fn (g mut Gen) expr(node ast.Expr) {
//println('cgen expr()')
match node {
@ -57,6 +47,18 @@ fn (g mut Gen) expr(node ast.Expr) {
ast.StringLiteral {
g.write('tos3("$it.val")')
}
ast.FnDecl {
g.writeln('$it.typ.name $it.name () { ')
for expr in it.exprs {
g.expr(expr)
}
g.writeln('}')
}
ast.Return {
g.write('return ')
g.expr(it.expr)
g.writeln(';')
}
ast.BinaryExpr {
g.expr(it.left)
match it.op {

View File

@ -18,6 +18,7 @@ mut:
lit string
//vars []string
table &table.Table
return_type types.Type
}
pub fn parse_expr(text string, table &table.Table) ast.Expr {
@ -33,6 +34,20 @@ pub fn parse_expr(text string, table &table.Table) ast.Expr {
return expr
}
pub fn (p mut Parser) get_type() types.Type {
defer {
p.next()
}
if p.lit == 'int' { return types.int_type }
else if p.lit == 'string' { return types.string_type }
else if p.lit == 'f64' { return types.f64_type }
else {
verror('bad type lit')
exit(1)
}
}
pub fn parse_file(text string, table &table.Table) ast.Program {
s := scanner.new_scanner(text)
mut exprs := []ast.Expr
@ -57,6 +72,24 @@ pub fn parse_file(text string, table &table.Table) ast.Program {
return ast.Program{exprs}
}
pub fn (p mut Parser) parse_block() []ast.Expr {
mut exprs := []ast.Expr
for {
//res := s.scan()
if p.tok == .eof || p.tok == .rcbr {
break
}
//println('expr at ' + p.tok.str())
expr,_ := p.expr(token.lowest_prec)
exprs << expr
}
p.next()
println('nr exprs in block = $exprs.len')
return exprs
}
/*
pub fn parse_stmt(text string) ast.Stmt {
mut s := scanner.new_scanner(text)
@ -78,12 +111,59 @@ fn (p mut Parser) next() {
p.lit = res.lit
}
fn (p mut Parser) check(expected token.Token) {
if p.tok != expected {
s := 'syntax error: unexpected `${p.tok.str()}`, expecting `${expected.str()}`'
verror(s)
}
p.next()
}
fn (p mut Parser) check_name() string {
name := p.lit
p.check(.name)
return name
}
// Implementation of Pratt Precedence
pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
// null denotation (prefix)
tok := p.tok
lit := p.lit
if p.tok == .name {
if p.tok == .key_fn {
p.next()
name := p.lit
println('fn decl $name')
p.check(.name)
p.check(.lpar)
p.check(.rpar)
// Return type
mut typ := types.void_type
if p.tok == .name {
typ = p.get_type()
p.return_type = typ
}
p.check(.lcbr)
//p.check(.rcbr)
println('OK!')
exprs := p.parse_block()
mut node := ast.Expr{}
node = ast.FnDecl{name: name, exprs: exprs, typ: typ}
return node, types.void_type
}
else if p.tok == .key_return {
p.next()
mut node := ast.Expr{}
expr, typ := p.expr(0)
if !types.check(p.return_type, typ) {
verror('bad ret type')
}
node = ast.Return{expr: expr}
return node, types.void_type
}
else if p.tok == .name {
name := p.lit
p.next()
if p.tok == .decl_assign {
@ -117,34 +197,30 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
}
p.next()
}
.str {
node = ast.StringLiteral{
val: lit
}
typ = types.string_type
}
.number {
if lit.contains('.') {
node = ast.FloatLiteral{
//val: lit.f64()
val: lit
}
typ = types.int_type
} else {
node = ast.IntegerLiteral{
val: lit.int()
}
typ = types.int_type
}
}
else {
// TODO: fix bug. note odd conditon instead of else if (same below)
if tok.is_scalar() {
if tok == .str {
node = ast.StringLiteral{
val: lit
}
typ = types.string_type
}
if tok == .number {
if lit.contains('.') {
node = ast.FloatLiteral{
//val: lit.f64()
val: lit
}
typ = types.int_type
} else {
node = ast.IntegerLiteral{
val: lit.int()
}
typ = types.int_type
}
}
// else {
// verror('bad scalar token')
// }
}
if !tok.is_scalar() && tok.is_unary() {
if tok.is_unary() {
expr,_ := p.expr(token.highest_prec)
node = ast.UnaryExpr{
// left: p.expr(token.highest_prec)

View File

@ -7,10 +7,16 @@ import (
)
fn test_parse_file() {
s := '12 + 3
x := 10
5+7
8+4
s := '
fn foo() string {
f := 23
return 10+4
}
12 + 3
x := 10
5+7
8+4
'
table := &table.Table{}
prog := parse_file(s, table)
@ -20,6 +26,7 @@ fn test_parse_file() {
fn test_parse_expr() {
//if true { return }
input := [
'2 + 3',
'2+2*4',

View File

@ -287,19 +287,20 @@ fn (t []Token) contains(val Token) bool {
}
pub fn (t Token) str() string {
lit := 't.lit'
if t == .number {
return 'number'
}
if t == .chartoken {
return '`lit`'
return 'char'//'`lit`'
}
if t == .str {
return "'lit'"
return 'str' //"'lit'"
}
/*
if t < .plus {
return lit // string, number etc
}
*/
return token_str[int(t)]
}

View File

@ -13,6 +13,7 @@ pub const (
void_type = Type{'void', 0}
int_type = Type{'int', 1}
string_type = Type{'string', 2}
f64_type = Type{'f64', 3}
)