FnDecl, Return, statement block
parent
6c16bac908
commit
66a07d7fe0
|
@ -793,13 +793,13 @@ fn (p mut Parser) type_decl() {
|
||||||
if p.tok == .key_struct {
|
if p.tok == .key_struct {
|
||||||
p.error('use `struct $name {` instead of `type $name 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()
|
p.next()
|
||||||
|
|
||||||
}
|
}
|
||||||
parent := p.get_type2()
|
mut parent := Type{}
|
||||||
// Sum type
|
// Sum type
|
||||||
is_sum := p.tok == .pipe
|
//is_sum := p.tok == .pipe
|
||||||
if is_sum {
|
if is_sum {
|
||||||
if !p.builtin_mod && p.mod != 'main' {
|
if !p.builtin_mod && p.mod != 'main' {
|
||||||
name = p.prepend_mod(name)
|
name = p.prepend_mod(name)
|
||||||
|
@ -815,10 +815,15 @@ fn (p mut Parser) type_decl() {
|
||||||
*/
|
*/
|
||||||
// Register the rest of them
|
// Register the rest of them
|
||||||
mut idx := 0
|
mut idx := 0
|
||||||
for p.tok == .pipe {
|
mut done := false
|
||||||
|
for {//p.tok == .pipe {
|
||||||
idx++
|
idx++
|
||||||
p.next()
|
//p.next()
|
||||||
child_type_name := p.check_name()
|
child_type_name := p.check_name()
|
||||||
|
//println('$idx $child_type_name')
|
||||||
|
if p.tok != .pipe {
|
||||||
|
done = true
|
||||||
|
}
|
||||||
if p.pass == .main {
|
if p.pass == .main {
|
||||||
// Update the type's parent
|
// Update the type's parent
|
||||||
//println('child=$child_type_name parent=$name')
|
//println('child=$child_type_name parent=$name')
|
||||||
|
@ -830,13 +835,17 @@ fn (p mut Parser) type_decl() {
|
||||||
p.table.rewrite_type(t)
|
p.table.rewrite_type(t)
|
||||||
p.cgen.consts << '#define SumType_$child_type_name $idx // DEF2'
|
p.cgen.consts << '#define SumType_$child_type_name $idx // DEF2'
|
||||||
}
|
}
|
||||||
|
if done {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
p.check(.pipe)
|
||||||
}
|
}
|
||||||
if p.pass == .decl {
|
if p.pass == .decl {
|
||||||
p.table.sum_types << name
|
p.table.sum_types << name
|
||||||
println(p.table.sum_types)
|
println(p.table.sum_types)
|
||||||
}
|
}
|
||||||
// Register the actual sum type
|
// Register the actual sum type
|
||||||
//println('registering sum $name')
|
println('registering sum $name')
|
||||||
p.table.register_type(Type{
|
p.table.register_type(Type{
|
||||||
name: name
|
name: name
|
||||||
mod: p.mod
|
mod: p.mod
|
||||||
|
@ -849,6 +858,10 @@ int typ;
|
||||||
} $name;
|
} $name;
|
||||||
')
|
')
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
parent = p.get_type2()
|
||||||
|
}
|
||||||
nt_pair := p.table.cgen_name_type_pair(name, parent.name)
|
nt_pair := p.table.cgen_name_type_pair(name, parent.name)
|
||||||
// TODO dirty C typedef hacks for DOOM
|
// TODO dirty C typedef hacks for DOOM
|
||||||
// Unknown type probably means it's a struct, and it's used before the struct is defined,
|
// Unknown type probably means it's a struct, and it's used before the struct is defined,
|
||||||
|
|
|
@ -11,10 +11,12 @@ import (
|
||||||
|
|
||||||
struct Foo {}
|
struct Foo {}
|
||||||
|
|
||||||
pub type Expr = Foo | IfExpr | BinaryExpr | UnaryExpr |
|
pub type Expr = BinaryExpr | UnaryExpr | IfExpr |
|
||||||
StringLiteral | IntegerLiteral | FloatLiteral | VarDecl
|
StringLiteral | IntegerLiteral | FloatLiteral | VarDecl |
|
||||||
|
FnDecl | Return
|
||||||
|
|
||||||
|
pub type Stmt = Foo//VarDecl
|
||||||
|
|
||||||
pub type Stmt = Foo | Foo //VarDecl
|
|
||||||
|
|
||||||
pub struct IntegerLiteral {
|
pub struct IntegerLiteral {
|
||||||
pub:
|
pub:
|
||||||
|
@ -32,6 +34,20 @@ pub:
|
||||||
val string
|
val string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct FnDecl {
|
||||||
|
pub:
|
||||||
|
name string
|
||||||
|
//stmts []Stmt
|
||||||
|
exprs []Expr
|
||||||
|
typ types.Type
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Return {
|
||||||
|
pub:
|
||||||
|
expr Expr
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
Binary(BinaryExpr)
|
Binary(BinaryExpr)
|
||||||
|
|
|
@ -31,16 +31,6 @@ pub fn (g mut Gen) writeln(s string) {
|
||||||
g.out.writeln(s)
|
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) {
|
fn (g mut Gen) expr(node ast.Expr) {
|
||||||
//println('cgen expr()')
|
//println('cgen expr()')
|
||||||
match node {
|
match node {
|
||||||
|
@ -57,6 +47,18 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
ast.StringLiteral {
|
ast.StringLiteral {
|
||||||
g.write('tos3("$it.val")')
|
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 {
|
ast.BinaryExpr {
|
||||||
g.expr(it.left)
|
g.expr(it.left)
|
||||||
match it.op {
|
match it.op {
|
||||||
|
|
|
@ -18,6 +18,7 @@ mut:
|
||||||
lit string
|
lit string
|
||||||
//vars []string
|
//vars []string
|
||||||
table &table.Table
|
table &table.Table
|
||||||
|
return_type types.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_expr(text string, table &table.Table) ast.Expr {
|
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
|
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 {
|
pub fn parse_file(text string, table &table.Table) ast.Program {
|
||||||
s := scanner.new_scanner(text)
|
s := scanner.new_scanner(text)
|
||||||
mut exprs := []ast.Expr
|
mut exprs := []ast.Expr
|
||||||
|
@ -57,6 +72,24 @@ pub fn parse_file(text string, table &table.Table) ast.Program {
|
||||||
return ast.Program{exprs}
|
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 {
|
pub fn parse_stmt(text string) ast.Stmt {
|
||||||
mut s := scanner.new_scanner(text)
|
mut s := scanner.new_scanner(text)
|
||||||
|
@ -78,12 +111,59 @@ fn (p mut Parser) next() {
|
||||||
p.lit = res.lit
|
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
|
// Implementation of Pratt Precedence
|
||||||
pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
|
pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
|
||||||
// null denotation (prefix)
|
// null denotation (prefix)
|
||||||
tok := p.tok
|
tok := p.tok
|
||||||
lit := p.lit
|
lit := p.lit
|
||||||
|
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 {
|
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
|
name := p.lit
|
||||||
p.next()
|
p.next()
|
||||||
if p.tok == .decl_assign {
|
if p.tok == .decl_assign {
|
||||||
|
@ -117,16 +197,14 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
|
||||||
}
|
}
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
else {
|
.str {
|
||||||
// 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
|
val: lit
|
||||||
}
|
}
|
||||||
typ = types.string_type
|
typ = types.string_type
|
||||||
|
|
||||||
}
|
}
|
||||||
if tok == .number {
|
.number {
|
||||||
if lit.contains('.') {
|
if lit.contains('.') {
|
||||||
node = ast.FloatLiteral{
|
node = ast.FloatLiteral{
|
||||||
//val: lit.f64()
|
//val: lit.f64()
|
||||||
|
@ -140,11 +218,9 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
|
||||||
typ = types.int_type
|
typ = types.int_type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// else {
|
else {
|
||||||
// verror('bad scalar token')
|
// TODO: fix bug. note odd conditon instead of else if (same below)
|
||||||
// }
|
if tok.is_unary() {
|
||||||
}
|
|
||||||
if !tok.is_scalar() && tok.is_unary() {
|
|
||||||
expr,_ := p.expr(token.highest_prec)
|
expr,_ := p.expr(token.highest_prec)
|
||||||
node = ast.UnaryExpr{
|
node = ast.UnaryExpr{
|
||||||
// left: p.expr(token.highest_prec)
|
// left: p.expr(token.highest_prec)
|
||||||
|
|
|
@ -7,7 +7,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
fn test_parse_file() {
|
fn test_parse_file() {
|
||||||
s := '12 + 3
|
s := '
|
||||||
|
fn foo() string {
|
||||||
|
f := 23
|
||||||
|
return 10+4
|
||||||
|
}
|
||||||
|
|
||||||
|
12 + 3
|
||||||
x := 10
|
x := 10
|
||||||
5+7
|
5+7
|
||||||
8+4
|
8+4
|
||||||
|
@ -20,6 +26,7 @@ fn test_parse_file() {
|
||||||
|
|
||||||
|
|
||||||
fn test_parse_expr() {
|
fn test_parse_expr() {
|
||||||
|
//if true { return }
|
||||||
input := [
|
input := [
|
||||||
'2 + 3',
|
'2 + 3',
|
||||||
'2+2*4',
|
'2+2*4',
|
||||||
|
|
|
@ -287,19 +287,20 @@ fn (t []Token) contains(val Token) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (t Token) str() string {
|
pub fn (t Token) str() string {
|
||||||
lit := 't.lit'
|
|
||||||
if t == .number {
|
if t == .number {
|
||||||
return 'number'
|
return 'number'
|
||||||
}
|
}
|
||||||
if t == .chartoken {
|
if t == .chartoken {
|
||||||
return '`lit`'
|
return 'char'//'`lit`'
|
||||||
}
|
}
|
||||||
if t == .str {
|
if t == .str {
|
||||||
return "'lit'"
|
return 'str' //"'lit'"
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if t < .plus {
|
if t < .plus {
|
||||||
return lit // string, number etc
|
return lit // string, number etc
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
return token_str[int(t)]
|
return token_str[int(t)]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ pub const (
|
||||||
void_type = Type{'void', 0}
|
void_type = Type{'void', 0}
|
||||||
int_type = Type{'int', 1}
|
int_type = Type{'int', 1}
|
||||||
string_type = Type{'string', 2}
|
string_type = Type{'string', 2}
|
||||||
|
f64_type = Type{'f64', 3}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue