cgen tests
parent
379c79025b
commit
651c7e8de1
|
@ -96,6 +96,20 @@ pub fn eprintln(s string) {
|
||||||
println(s)
|
println(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn eprint(s string) {
|
||||||
|
if isnil(s.str) {
|
||||||
|
panic('eprint(NIL)')
|
||||||
|
}
|
||||||
|
$if !windows {
|
||||||
|
C.fflush(stdout)
|
||||||
|
C.fflush(stderr)
|
||||||
|
C.fprintf(stderr, '%.*s', s.len, s.str)
|
||||||
|
C.fflush(stderr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
print(s)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn print(s string) {
|
pub fn print(s string) {
|
||||||
$if windows {
|
$if windows {
|
||||||
C.wprintf(s.to_wide())
|
C.wprintf(s.to_wide())
|
||||||
|
|
|
@ -30,7 +30,7 @@ pub:
|
||||||
val string
|
val string
|
||||||
}
|
}
|
||||||
|
|
||||||
// module decleration
|
// module declaration
|
||||||
pub struct Module {
|
pub struct Module {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
|
|
|
@ -7,11 +7,12 @@ import (
|
||||||
|
|
||||||
struct Gen {
|
struct Gen {
|
||||||
out strings.Builder
|
out strings.Builder
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen(program ast.Program) string {
|
pub fn gen(program ast.Program) string {
|
||||||
mut g := Gen{out:strings.new_builder(100)}
|
mut g := Gen{
|
||||||
|
out: strings.new_builder(100)
|
||||||
|
}
|
||||||
for expr in program.exprs {
|
for expr in program.exprs {
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
g.writeln('')
|
g.writeln('')
|
||||||
|
@ -19,9 +20,7 @@ pub fn gen(program ast.Program) string {
|
||||||
return (g.out.str())
|
return (g.out.str())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (g &Gen) save() {
|
pub fn (g &Gen) save() {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (g mut Gen) write(s string) {
|
pub fn (g mut Gen) write(s string) {
|
||||||
g.out.write(s)
|
g.out.write(s)
|
||||||
|
@ -32,7 +31,7 @@ pub fn (g mut Gen) writeln(s string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
ast.IntegerLiteral {
|
ast.IntegerLiteral {
|
||||||
g.write(it.val.str())
|
g.write(it.val.str())
|
||||||
|
@ -48,7 +47,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
g.write('tos3("$it.val")')
|
g.write('tos3("$it.val")')
|
||||||
}
|
}
|
||||||
ast.FnDecl {
|
ast.FnDecl {
|
||||||
g.writeln('$it.typ.name $it.name () { ')
|
g.writeln('$it.typ.name ${it.name}() { ')
|
||||||
for expr in it.exprs {
|
for expr in it.exprs {
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
|
@ -62,17 +61,27 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||||
ast.BinaryExpr {
|
ast.BinaryExpr {
|
||||||
g.expr(it.left)
|
g.expr(it.left)
|
||||||
match it.op {
|
match it.op {
|
||||||
.plus { g.write(' + ') }
|
.plus {
|
||||||
.minus { g.write(' - ') }
|
g.write(' + ')
|
||||||
.mul { g.write(' * ') }
|
}
|
||||||
.div { g.write(' / ') }
|
.minus {
|
||||||
.plus_assign { g.write(' += ') }
|
g.write(' - ')
|
||||||
|
}
|
||||||
|
.mul {
|
||||||
|
g.write(' * ')
|
||||||
|
}
|
||||||
|
.div {
|
||||||
|
g.write(' / ')
|
||||||
|
}
|
||||||
|
.plus_assign {
|
||||||
|
g.write(' += ')
|
||||||
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
g.expr(it.right)
|
g.expr(it.right)
|
||||||
// if typ.name != typ2.name {
|
// if typ.name != typ2.name {
|
||||||
//verror('bad types $typ.name $typ2.name')
|
// verror('bad types $typ.name $typ2.name')
|
||||||
//}
|
// }
|
||||||
}
|
}
|
||||||
ast.VarDecl {
|
ast.VarDecl {
|
||||||
g.write('$it.typ.name $it.name = ')
|
g.write('$it.typ.name $it.name = ')
|
||||||
|
@ -89,4 +98,3 @@ fn verror(s string) {
|
||||||
println(s)
|
println(s)
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
import (
|
||||||
|
os
|
||||||
|
v.parser
|
||||||
|
v.ast
|
||||||
|
v.cgen
|
||||||
|
v.table
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
nr_tests = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
fn test_c_files() {
|
||||||
|
println('Running V => C tests')
|
||||||
|
for i in 1 .. nr_tests + 1 {
|
||||||
|
text := os.read_file('tests/${i}.v') or {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
ctext := os.read_file('tests/${i}.c') or {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
table := &table.Table{}
|
||||||
|
program := parser.parse_file(text, table)
|
||||||
|
res := cgen.gen(program)
|
||||||
|
if compare_texts(res, ctext) {
|
||||||
|
eprintln('${i}... OK')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
eprintln('${i}... FAIL')
|
||||||
|
eprintln('expected:\n$ctext\ngot:\n$res')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare_texts(a, b string) bool {
|
||||||
|
lines_a := a.trim_space().split_into_lines()
|
||||||
|
lines_b := b.trim_space().split_into_lines()
|
||||||
|
if lines_a.len != lines_b.len {
|
||||||
|
println('different len')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i, line_a in lines_a {
|
||||||
|
line_b := lines_b[i]
|
||||||
|
if line_a.trim_space() != line_b.trim_space() {
|
||||||
|
println('!' + line_a)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
int main() {
|
||||||
|
int a = 10;
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
fn main() int {
|
||||||
|
a := 10
|
||||||
|
return 0
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
int function1() {
|
||||||
|
int a = 10 + 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void function2() {
|
||||||
|
int x = 0;
|
||||||
|
f64 f = 10.1;
|
||||||
|
string s = tos3("hi");
|
||||||
|
int m = 10;
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
fn function1() int {
|
||||||
|
a := 10 + 1
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// comment
|
||||||
|
fn function2() {
|
||||||
|
x := 0
|
||||||
|
f := 10.1
|
||||||
|
s := 'hi'
|
||||||
|
mut m := 10
|
||||||
|
}
|
|
@ -72,7 +72,7 @@ pub fn parse_file(text string, table &table.Table) ast.Program {
|
||||||
expr,_ := p.expr(token.lowest_prec)
|
expr,_ := p.expr(token.lowest_prec)
|
||||||
exprs << expr
|
exprs << expr
|
||||||
}
|
}
|
||||||
println('nr exprs = $exprs.len')
|
// println('nr exprs = $exprs.len')
|
||||||
println(exprs[0])
|
println(exprs[0])
|
||||||
return ast.Program{
|
return ast.Program{
|
||||||
exprs}
|
exprs}
|
||||||
|
@ -90,7 +90,7 @@ pub fn (p mut Parser) parse_block() []ast.Expr {
|
||||||
exprs << expr
|
exprs << expr
|
||||||
}
|
}
|
||||||
p.next()
|
p.next()
|
||||||
println('nr exprs in block = $exprs.len')
|
// println('nr exprs in block = $exprs.len')
|
||||||
return exprs
|
return exprs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,6 +146,9 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
|
||||||
.key_return {
|
.key_return {
|
||||||
return p.return_stmt()
|
return p.return_stmt()
|
||||||
}
|
}
|
||||||
|
.key_mut {
|
||||||
|
return p.var_decl()
|
||||||
|
}
|
||||||
.name {
|
.name {
|
||||||
if p.peek_tok.kind == .decl_assign {
|
if p.peek_tok.kind == .decl_assign {
|
||||||
return p.var_decl()
|
return p.var_decl()
|
||||||
|
@ -159,9 +162,7 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
|
||||||
}
|
}
|
||||||
.lpar {
|
.lpar {
|
||||||
node,typ = p.expr(0)
|
node,typ = p.expr(0)
|
||||||
if p.tok.kind != .rpar {
|
p.check(.rpar)
|
||||||
panic('Parse Error: expected )')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p.next()
|
p.next()
|
||||||
|
@ -173,6 +174,9 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
|
||||||
op: p.tok.kind
|
op: p.tok.kind
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
verror('!unknown token ' + p.tok.str())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// left binding power
|
// left binding power
|
||||||
|
@ -256,7 +260,7 @@ fn (p mut Parser) parse_number_literal() (ast.Expr,types.Type) {
|
||||||
// val: lit.f64()
|
// val: lit.f64()
|
||||||
val: lit
|
val: lit
|
||||||
}
|
}
|
||||||
typ = types.int_type
|
typ = types.f64_type
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
node = ast.IntegerLiteral{
|
node = ast.IntegerLiteral{
|
||||||
|
@ -283,7 +287,7 @@ fn (p mut Parser) import_stmt() (ast.Expr,types.Type) {
|
||||||
fn (p mut Parser) fn_decl() (ast.Expr,types.Type) {
|
fn (p mut Parser) fn_decl() (ast.Expr,types.Type) {
|
||||||
p.check(.key_fn)
|
p.check(.key_fn)
|
||||||
name := p.tok.lit
|
name := p.tok.lit
|
||||||
println('fn decl $name')
|
// println('fn decl $name')
|
||||||
p.check(.name)
|
p.check(.name)
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
|
@ -295,7 +299,6 @@ fn (p mut Parser) fn_decl() (ast.Expr,types.Type) {
|
||||||
}
|
}
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
// p.check(.rcbr)
|
// p.check(.rcbr)
|
||||||
println('OK!')
|
|
||||||
exprs := p.parse_block()
|
exprs := p.parse_block()
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
node = ast.FnDecl{
|
node = ast.FnDecl{
|
||||||
|
@ -307,7 +310,7 @@ fn (p mut Parser) fn_decl() (ast.Expr,types.Type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) return_stmt() (ast.Expr,types.Type) {
|
fn (p mut Parser) return_stmt() (ast.Expr,types.Type) {
|
||||||
println('return st')
|
// println('return st')
|
||||||
p.next()
|
p.next()
|
||||||
expr,t := p.expr(0)
|
expr,t := p.expr(0)
|
||||||
if !types.check(p.return_type, t) {
|
if !types.check(p.return_type, t) {
|
||||||
|
@ -321,6 +324,16 @@ fn (p mut Parser) return_stmt() (ast.Expr,types.Type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) var_decl() (ast.Expr,types.Type) {
|
fn (p mut Parser) var_decl() (ast.Expr,types.Type) {
|
||||||
|
is_mut := p.tok.kind == .key_mut // || p.prev_tok == .key_for
|
||||||
|
is_static := p.tok.kind == .key_static
|
||||||
|
if p.tok.kind == .key_mut {
|
||||||
|
p.check(.key_mut)
|
||||||
|
// p.fspace()
|
||||||
|
}
|
||||||
|
if p.tok.kind == .key_static {
|
||||||
|
p.check(.key_static)
|
||||||
|
// p.fspace()
|
||||||
|
}
|
||||||
name := p.tok.lit
|
name := p.tok.lit
|
||||||
p.next()
|
p.next()
|
||||||
p.next()
|
p.next()
|
||||||
|
@ -329,8 +342,8 @@ fn (p mut Parser) var_decl() (ast.Expr,types.Type) {
|
||||||
verror('redefinition of `$name`')
|
verror('redefinition of `$name`')
|
||||||
}
|
}
|
||||||
p.table.names << name
|
p.table.names << name
|
||||||
println(p.table.names)
|
// println(p.table.names)
|
||||||
println('added $name')
|
// println('added $name')
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
// TODO can't return VarDecl{}
|
// TODO can't return VarDecl{}
|
||||||
node = ast.VarDecl{
|
node = ast.VarDecl{
|
||||||
|
|
Loading…
Reference in New Issue