Skip to content

Commit

Permalink
refac(gen): move generation of test main function into transformer (#294
Browse files Browse the repository at this point in the history
)
  • Loading branch information
serkonda7 authored Jan 20, 2025
1 parent 3cb87e5 commit 350abaa
Show file tree
Hide file tree
Showing 11 changed files with 141 additions and 84 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ All notable changes are documented in this file.
- lexer: Disallow floats with trailing decimal point
- fix(c): Prevent c error if blank identifier is used

### Compiler internals
- refac(gen): move generation of test main function into transformer


## 0.0.8 - 2024-12-25
### Breaking
Expand Down
6 changes: 4 additions & 2 deletions lib/bait/builder/builder.bt
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ pub fun compile(prefs preference.Prefs) i32 {
prefs = b.prefs
table = b.parser.table
sema_ctx = sema_ctx
gen_ctx = &context.GenContext{}
files = b.parsed_files
}
b.checker.toplevel_redefinitions()
Expand Down Expand Up @@ -190,7 +191,7 @@ pub fun compile(prefs preference.Prefs) i32 {
// Run the type resolver and checker
timers.start('CHECK')
b.parsed_files = sorted_files
b.checker.check_files(sorted_files)
b.checker.check_files(b.parsed_files)
timers.show('CHECK')

if b.print_errors_and_warnings(false) {
Expand All @@ -201,8 +202,9 @@ pub fun compile(prefs preference.Prefs) i32 {

// Transformer
timers.start('TRANSFORM')
trans := transformer.Transformer{
mut trans := transformer.Transformer{
prefs = b.prefs
gen_ctx = b.checker.gen_ctx
}
trans.transform_files(b.parsed_files)
timers.show('TRANSFORM')
Expand Down
16 changes: 15 additions & 1 deletion lib/bait/checker/checker.bt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub struct Checker{
prefs preference.Prefs
table ast.Table
sema_ctx &context.SemanticContext
pub mut gen_ctx &context.GenContext
mut files []&ast.File
mut file ast.File
mut scope context.Scope
Expand Down Expand Up @@ -70,11 +71,24 @@ pub fun (mut c Checker) check_files(files []&ast.File) {
resolve_runs += 1
}

// Test mode special checks
if c.prefs.is_test {
c.change_file(files.last())

if c.gen_ctx.test_fun_names.length == 0 {
c.generic_error("${c.path} contains no tests")
return
}

return
}

// no main function needed for libraries, tests and script mode
if c.prefs.is_library or c.prefs.is_test or c.prefs.is_script {
if c.prefs.is_library or c.prefs.is_script {
return
}

// Main function checks
if not c.has_main_pkg_files {
c.generic_error('project must have a main package or be compiled as a library')
} else if not c.has_main_fun {
Expand Down
10 changes: 10 additions & 0 deletions lib/bait/checker/fun.bt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ fun (mut c Checker) fun_decl(mut node ast.FunDecl) {
}
}
}
} else {
if node.is_test {
c.gen_ctx.test_fun_names.push(node.mix_name)
} else if c.prefs.is_test {
if node.name == "testsuite_begin" {
c.gen_ctx.has_test_begin = true
} else if node.name == "testsuite_end" {
c.gen_ctx.has_test_end = true
}
}
}

if node.generic_names.length > 0 and c.cur_concrete_types.length == 0 {
Expand Down
11 changes: 11 additions & 0 deletions lib/bait/context/gen_ctx.bt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-FileCopyrightText: 2023-present Lukas Neubert <[email protected]>
// SPDX-License-Identifier: MIT
package context

// Information shared between checker, transformer and gen
pub struct GenContext {
// Testing
global has_test_begin bool
global has_test_end bool
global test_fun_names []string
}
File renamed without changes.
33 changes: 0 additions & 33 deletions lib/bait/gen/c/cgen.bt
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,6 @@ pub fun gen(files []ast.File, table ast.Table, pref preference.Prefs) string {
g.out += "\n"
}

// Main
if pref.is_test {
g.gen_test_main()
}
if not g.pref.is_library {
g.c_main()
}
Expand Down Expand Up @@ -99,35 +95,6 @@ fun (g Gen) headers() string {
return headers + '\n'
}

fun (mut g Gen) gen_test_main() {
mut nr_test_funs := 0
g.writeln('int bait_main() {')
g.indent += 2
if g.has_test_begin {
g.writeln('testsuite_begin();')
}
for key, func in g.table.fun_decls {
if func.is_test {
nr_test_funs += 1
name := c_esc(func.mix_name)
esc_path := g.path.replace('\\', '\\\\')
g.writeln('TestRunner_set_test_info(&builtin__test_runner, from_c_string("${esc_path}"), from_c_string("${name}"));')
g.writeln('${name}();')
}
}
if g.has_test_end {
g.writeln('testsuite_end();')
}
g.writeln('exit(TestRunner_exit_code(builtin__test_runner));')
g.indent -= 2
g.writeln('}\n')

if nr_test_funs == 0 {
errors.generic_error('${g.path} contains no tests')
exit(1)
}
}

fun (mut g Gen) c_main() {
g.writeln('int main(int argc, char* argv[]) {')
g.writeln(g.main_inits_out)
Expand Down
32 changes: 0 additions & 32 deletions lib/bait/gen/js/jsgen.bt
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,6 @@ pub fun gen(files []ast.File, table ast.Table, pref preference.Prefs) string {
g.out += "\n"
}

if pref.is_test {
g.gen_test_main()
}
if not pref.is_library {
g.main_call()
}
Expand Down Expand Up @@ -181,35 +178,6 @@ fun (mut g Gen) save_stmt_offset() {
g.stmt_offsets.push(g.out.length)
}

fun (mut g Gen) gen_test_main() {
mut nr_test_funs := 0
g.writeln('function main() {')
g.indent += 1
if g.has_test_begin {
g.writeln('testsuite_begin()')
}
for key, func in g.table.fun_decls {
if func.is_test {
nr_test_funs += 1
name := js_esc(func.mix_name)
esc_path := g.path.replace('\\', '\\\\')
g.writeln('TestRunner_set_test_info(builtin__test_runner, from_js_string("${esc_path}"), from_js_string("${name}"))')
g.writeln('${name}()')
}
}
if g.has_test_end {
g.writeln('testsuite_end()')
}
g.writeln('exit(TestRunner_exit_code(builtin__test_runner))')
g.indent -= 1
g.writeln('}')

if nr_test_funs == 0 {
errors.generic_error('${g.path} contains no tests')
exit(1)
}
}

fun (mut g Gen) main_call() {
g.out += "main()"
}
Expand Down
6 changes: 5 additions & 1 deletion lib/bait/gen/js/stmt.bt
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ fun (mut g Gen) stmt(stmt ast.Stmt) {
g.struct_decl(stmt)
} else if stmt is ast.TypeDecl {
g.type_decl(stmt)
} else {}
} else if stmt is ast.Void {
// nothing to do
} else {
panic("cannot gen ${stmt}")
}
}

fun (mut g Gen) assert_stmt(node ast.AssertStmt) {
Expand Down
69 changes: 69 additions & 0 deletions lib/bait/transformer/gen_test_main.bt
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// SPDX-FileCopyrightText: 2023-present Lukas Neubert <[email protected]>
// SPDX-License-Identifier: MIT
package transformer

import bait.ast

fun (t Transformer) gen_test_main() &ast.File {
mut test_main := ast.FunDecl{
mix_name = "main"
name = "main"
}

if t.gen_ctx.has_test_begin {
test_main.stmts.push(ast.ExprStmt{
expr = ast.CallExpr{
mix_name = "testsuite_begin"
name = "testsuite_begin"
}
})
}

esc_path := t.path.replace("\\", "\\\\")
for name in t.gen_ctx.test_fun_names {
mut val := 'TestRunner_set_test_info(builtin__test_runner, from_js_string("${esc_path}"), from_js_string("${name}"))'
if t.prefs.backend == .c {
val = 'TestRunner_set_test_info(&builtin__test_runner, from_c_string("${esc_path}"), from_c_string("${name}"))'
}
test_main.stmts.push(ast.ExprStmt{
// TODO properly transform this (requires changes to method calls)
expr = ast.HashExpr{
val = val
}
})
test_main.stmts.push(ast.ExprStmt{
expr = ast.CallExpr{
mix_name = name
name = name
}
})
}

if t.gen_ctx.has_test_end {
test_main.stmts.push(ast.ExprStmt{
expr = ast.CallExpr{
mix_name = "testsuite_end"
name = "testsuite_end"
}
})
}

// exit(test_runner.exit_code())
test_main.stmts.push(ast.ExprStmt{
expr = ast.CallExpr{
mix_name = "exit"
name = "exit"
args = [
ast.CallArg{
// TODO properly transform this (requires changes to method calls)
expr = ast.HashExpr{
val = "TestRunner_exit_code(builtin__test_runner)"
}
}
]
}
})
return ast.File{
stmts = [test_main as ast.Stmt]
}
}
Loading

0 comments on commit 350abaa

Please sign in to comment.