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 == .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 | 		name := p.lit | ||||||
| 		p.next() | 		p.next() | ||||||
| 		if p.tok == .decl_assign { | 		if p.tok == .decl_assign { | ||||||
|  | @ -117,34 +197,30 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) { | ||||||
| 			} | 			} | ||||||
| 			p.next() | 			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 { | 		else { | ||||||
| 			// TODO: fix bug. note odd conditon instead of else if (same below)
 | 			// TODO: fix bug. note odd conditon instead of else if (same below)
 | ||||||
| 			if tok.is_scalar() { | 			if tok.is_unary() { | ||||||
| 				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() { |  | ||||||
| 				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,10 +7,16 @@ import ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| fn test_parse_file() { | fn test_parse_file() { | ||||||
| 	s := '12 + 3 | 	s := ' | ||||||
| 	x := 10 | fn foo() string { | ||||||
| 	5+7 | 	f := 23 | ||||||
| 	8+4 | 	return 10+4 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 12 + 3 | ||||||
|  | x := 10 | ||||||
|  | 5+7 | ||||||
|  | 8+4 | ||||||
| ' | ' | ||||||
| 	table := &table.Table{} | 	table := &table.Table{} | ||||||
| 	prog := parse_file(s, table) | 	prog := parse_file(s, table) | ||||||
|  | @ -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