FnDecl, Return, statement block
							parent
							
								
									6c16bac908
								
							
						
					
					
						commit
						66a07d7fe0
					
				|  | @ -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,
 | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
|  | @ -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 == .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,16 +197,14 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) { | |||
| 			} | ||||
| 			p.next() | ||||
| 		} | ||||
| 		else { | ||||
| 			// TODO: fix bug. note odd conditon instead of else if (same below)
 | ||||
| 			if tok.is_scalar() { | ||||
| 				if tok == .str { | ||||
| 		.str { | ||||
| 			node = ast.StringLiteral{ | ||||
| 				val: lit | ||||
| 			} | ||||
| 			typ = types.string_type | ||||
| 
 | ||||
| 		} | ||||
| 				if tok == .number { | ||||
| 		.number { | ||||
| 			if lit.contains('.') { | ||||
| 				node = ast.FloatLiteral{ | ||||
| 					//val: lit.f64()
 | ||||
|  | @ -140,11 +218,9 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) { | |||
| 				typ = types.int_type | ||||
| 			} | ||||
| 		} | ||||
| 				// else {
 | ||||
| 				// verror('bad scalar token')
 | ||||
| 				// }
 | ||||
| 			} | ||||
| 			if !tok.is_scalar() && tok.is_unary() { | ||||
| 		else { | ||||
| 			// TODO: fix bug. note odd conditon instead of else if (same below)
 | ||||
| 			if tok.is_unary() { | ||||
| 				expr,_ := p.expr(token.highest_prec) | ||||
| 				node = ast.UnaryExpr{ | ||||
| 					// left: p.expr(token.highest_prec)
 | ||||
|  |  | |||
|  | @ -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', | ||||
|  |  | |||
|  | @ -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)] | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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} | ||||
| ) | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue