compiler: streamline main function handling
* compiler: streamline C main function generation * fix most tests * compiler: fix for 'go update()' in graph.v . More precise parser error messages. * Fix temporarily examples/hot_reload/message.v by using os inside it (os.clear). * Make graph.v easier to quickly modify by defining y outside the loop. * Fix failure of /v/nv/compiler/tests/defer_test.v when run with 'v -g' (#line directive was not on its own line, but right after } ). * Do not pass the os.args to tests, even if the tests import os (they are more stable when run in a controlled environment). * fix declared and not used in the js backend. * fix js main => main__main too.pull/2159/head
parent
0160c7a89d
commit
a4cbe78d97
|
@ -63,7 +63,7 @@ fn (g mut CGen) genln(s string) {
|
||||||
g.cur_line = '$g.cur_line $s'
|
g.cur_line = '$g.cur_line $s'
|
||||||
if g.cur_line != '' {
|
if g.cur_line != '' {
|
||||||
if g.line_directives && g.cur_line.trim_space() != '' {
|
if g.line_directives && g.cur_line.trim_space() != '' {
|
||||||
g.lines << '#line $g.line "$g.file"'
|
g.lines << '\n#line $g.line "$g.file"'
|
||||||
}
|
}
|
||||||
g.lines << g.cur_line
|
g.lines << g.cur_line
|
||||||
g.prev_line = g.cur_line
|
g.prev_line = g.cur_line
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
module main
|
module main
|
||||||
|
|
||||||
import(
|
import(
|
||||||
os
|
|
||||||
strings
|
strings
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -34,6 +33,7 @@ mut:
|
||||||
is_decl bool // type myfn fn(int, int)
|
is_decl bool // type myfn fn(int, int)
|
||||||
defer_text []string
|
defer_text []string
|
||||||
//gen_types []string
|
//gen_types []string
|
||||||
|
fn_name_sp ScannerPos
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p &Parser) find_var(name string) ?Var {
|
fn (p &Parser) find_var(name string) ?Var {
|
||||||
|
@ -215,6 +215,7 @@ fn (p mut Parser) fn_decl() {
|
||||||
else {
|
else {
|
||||||
f.name = p.check_name()
|
f.name = p.check_name()
|
||||||
}
|
}
|
||||||
|
f.fn_name_sp = p.scanner.get_scanner_pos()
|
||||||
// C function header def? (fn C.NSMakeRect(int,int,int,int))
|
// C function header def? (fn C.NSMakeRect(int,int,int,int))
|
||||||
is_c := f.name == 'C' && p.tok == .dot
|
is_c := f.name == 'C' && p.tok == .dot
|
||||||
// Just fn signature? only builtin.v + default build mode
|
// Just fn signature? only builtin.v + default build mode
|
||||||
|
@ -244,7 +245,7 @@ fn (p mut Parser) fn_decl() {
|
||||||
}
|
}
|
||||||
// full mod function name
|
// full mod function name
|
||||||
// os.exit ==> os__exit()
|
// os.exit ==> os__exit()
|
||||||
if !is_c && !p.builtin_mod && p.mod != 'main' && receiver_typ.len == 0 {
|
if !is_c && !p.builtin_mod && receiver_typ.len == 0 {
|
||||||
f.name = p.prepend_mod(f.name)
|
f.name = p.prepend_mod(f.name)
|
||||||
}
|
}
|
||||||
if p.first_pass() && receiver_typ.len == 0 {
|
if p.first_pass() && receiver_typ.len == 0 {
|
||||||
|
@ -318,14 +319,12 @@ fn (p mut Parser) fn_decl() {
|
||||||
}
|
}
|
||||||
// Register function
|
// Register function
|
||||||
f.typ = typ
|
f.typ = typ
|
||||||
mut str_args := f.str_args(p.table)
|
str_args := f.str_args(p.table)
|
||||||
// Special case for main() args
|
// Special case for main() args
|
||||||
if f.name == 'main' && !has_receiver {
|
if f.name == 'main__main' && !has_receiver {
|
||||||
if str_args != '' || typ != 'void' {
|
if str_args != '' || typ != 'void' {
|
||||||
p.error('fn main must have no arguments and no return values')
|
p.error_with_position('fn main must have no arguments and no return values', f.fn_name_sp)
|
||||||
}
|
}
|
||||||
typ = 'int'
|
|
||||||
str_args = 'int argc, char** argv'
|
|
||||||
}
|
}
|
||||||
dll_export_linkage := if p.os == .msvc && p.attr == 'live' && p.pref.is_so {
|
dll_export_linkage := if p.os == .msvc && p.attr == 'live' && p.pref.is_so {
|
||||||
'__declspec(dllexport) '
|
'__declspec(dllexport) '
|
||||||
|
@ -341,7 +340,7 @@ fn (p mut Parser) fn_decl() {
|
||||||
// Internally it's still stored as "register" in type User
|
// Internally it's still stored as "register" in type User
|
||||||
mut fn_name_cgen := p.table.fn_gen_name(f)
|
mut fn_name_cgen := p.table.fn_gen_name(f)
|
||||||
// Start generation of the function body
|
// Start generation of the function body
|
||||||
skip_main_in_test := f.name == 'main' && p.pref.is_test
|
skip_main_in_test := false
|
||||||
if !is_c && !is_live && !is_sig && !is_fn_header && !skip_main_in_test {
|
if !is_c && !is_live && !is_sig && !is_fn_header && !skip_main_in_test {
|
||||||
if p.pref.obfuscate {
|
if p.pref.obfuscate {
|
||||||
p.genln('; // $f.name')
|
p.genln('; // $f.name')
|
||||||
|
@ -434,7 +433,7 @@ fn (p mut Parser) fn_decl() {
|
||||||
fn_decl += '; // $f.name'
|
fn_decl += '; // $f.name'
|
||||||
}
|
}
|
||||||
// Add function definition to the top
|
// Add function definition to the top
|
||||||
if !is_c && f.name != 'main' && p.first_pass() {
|
if !is_c && p.first_pass() {
|
||||||
// TODO hack to make Volt compile without -embed_vlib
|
// TODO hack to make Volt compile without -embed_vlib
|
||||||
if f.name == 'darwin__nsstring' && p.pref.build_mode == .default_mode {
|
if f.name == 'darwin__nsstring' && p.pref.build_mode == .default_mode {
|
||||||
return
|
return
|
||||||
|
@ -447,37 +446,10 @@ fn (p mut Parser) fn_decl() {
|
||||||
//p.genln('// live_function body start')
|
//p.genln('// live_function body start')
|
||||||
p.genln('pthread_mutex_lock(&live_fn_mutex);')
|
p.genln('pthread_mutex_lock(&live_fn_mutex);')
|
||||||
}
|
}
|
||||||
if f.name == 'main' || f.name == 'WinMain' {
|
|
||||||
p.genln('init_consts();')
|
if f.name == 'main__main' || f.name == 'main' || f.name == 'WinMain' {
|
||||||
if 'os' in p.table.imports {
|
|
||||||
if f.name == 'main' {
|
|
||||||
p.genln('os__args = os__init_os_args(argc, (byteptr*)argv);')
|
|
||||||
}
|
|
||||||
else if f.name == 'WinMain' {
|
|
||||||
p.genln('os__args = os__parse_windows_cmd_line(pCmdLine);')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// We are in live code reload mode, call the .so loader in bg
|
|
||||||
if p.pref.is_live {
|
|
||||||
file_base := os.filename(p.file_path).replace('.v', '')
|
|
||||||
if p.os != .windows && p.os != .msvc {
|
|
||||||
so_name := file_base + '.so'
|
|
||||||
p.genln('
|
|
||||||
load_so("$so_name");
|
|
||||||
pthread_t _thread_so;
|
|
||||||
pthread_create(&_thread_so , NULL, &reload_so, NULL); ')
|
|
||||||
} else {
|
|
||||||
so_name := file_base + if p.os == .msvc {'.dll'} else {'.so'}
|
|
||||||
p.genln('
|
|
||||||
live_fn_mutex = CreateMutexA(0, 0, 0);
|
|
||||||
load_so("$so_name");
|
|
||||||
unsigned long _thread_so;
|
|
||||||
_thread_so = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&reload_so, 0, 0, 0);
|
|
||||||
')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if p.pref.is_test && !p.scanner.file_path.contains('/volt') {
|
if p.pref.is_test && !p.scanner.file_path.contains('/volt') {
|
||||||
p.error('tests cannot have function `main`')
|
p.error_with_position('tests cannot have function `main`', f.fn_name_sp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// println('is_c=$is_c name=$f.name')
|
// println('is_c=$is_c name=$f.name')
|
||||||
|
@ -486,7 +458,7 @@ _thread_so = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&reload_so, 0, 0, 0);
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Profiling mode? Start counting at the beginning of the function (save current time).
|
// Profiling mode? Start counting at the beginning of the function (save current time).
|
||||||
if p.pref.is_prof && f.name != 'main' && f.name != 'time__ticks' {
|
if p.pref.is_prof && f.name != 'time__ticks' {
|
||||||
p.genln('double _PROF_START = time__ticks();//$f.name')
|
p.genln('double _PROF_START = time__ticks();//$f.name')
|
||||||
cgen_name := p.table.fn_gen_name(f)
|
cgen_name := p.table.fn_gen_name(f)
|
||||||
if f.defer_text.len > f.scope_level {
|
if f.defer_text.len > f.scope_level {
|
||||||
|
@ -509,8 +481,8 @@ _thread_so = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&reload_so, 0, 0, 0);
|
||||||
p.genln(f.defer_text[f.scope_level])
|
p.genln(f.defer_text[f.scope_level])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if typ != 'void' && !p.returns && f.name != 'main' && f.name != 'WinMain' {
|
if typ != 'void' && !p.returns {
|
||||||
p.error('$f.name must return "$typ"')
|
p.error_with_position('$f.name must return "$typ"', f.fn_name_sp)
|
||||||
}
|
}
|
||||||
if p.attr == 'live' && p.pref.is_so {
|
if p.attr == 'live' && p.pref.is_so {
|
||||||
//p.genln('// live_function body end')
|
//p.genln('// live_function body end')
|
||||||
|
|
|
@ -36,7 +36,7 @@ fn (p mut Parser) gen_fn_decl(f Fn, typ, _str_args string) {
|
||||||
fn (p mut Parser) gen_blank_identifier_assign() {
|
fn (p mut Parser) gen_blank_identifier_assign() {
|
||||||
p.check_name()
|
p.check_name()
|
||||||
p.check_space(.assign)
|
p.check_space(.assign)
|
||||||
typ := p.bool_expression()
|
p.bool_expression()
|
||||||
or_else := p.tok == .key_orelse
|
or_else := p.tok == .key_orelse
|
||||||
//tmp := p.get_tmp()
|
//tmp := p.get_tmp()
|
||||||
if or_else {
|
if or_else {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
module main
|
module main
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
fn (v &V) generate_hotcode_reloading_compiler_flags() []string {
|
fn (v &V) generate_hotcode_reloading_compiler_flags() []string {
|
||||||
mut a := []string
|
mut a := []string
|
||||||
|
@ -35,6 +36,30 @@ fn (v &V) generate_hotcode_reloading_declarations() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (v &V) generate_hotcode_reloading_main_caller() {
|
||||||
|
if !v.pref.is_live { return }
|
||||||
|
// We are in live code reload mode, so start the .so loader in the background
|
||||||
|
mut cgen := v.cgen
|
||||||
|
cgen.genln('')
|
||||||
|
file_base := os.filename(v.dir).replace('.v', '')
|
||||||
|
if !(v.os == .windows || v.os == .msvc) {
|
||||||
|
// unix:
|
||||||
|
so_name := file_base + '.so'
|
||||||
|
cgen.genln(' char *live_library_name = "$so_name";')
|
||||||
|
cgen.genln(' load_so(live_library_name);')
|
||||||
|
cgen.genln(' pthread_t _thread_so;')
|
||||||
|
cgen.genln(' pthread_create(&_thread_so , NULL, &reload_so, live_library_name);')
|
||||||
|
} else {
|
||||||
|
// windows:
|
||||||
|
so_name := file_base + if v.os == .msvc {'.dll'} else {'.so'}
|
||||||
|
cgen.genln(' char *live_library_name = "$so_name";')
|
||||||
|
cgen.genln(' live_fn_mutex = CreateMutexA(0, 0, 0);')
|
||||||
|
cgen.genln(' load_so(live_library_name);')
|
||||||
|
cgen.genln(' unsigned long _thread_so;')
|
||||||
|
cgen.genln(' _thread_so = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&reload_so, 0, 0, 0);')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn (v &V) generate_hot_reload_code() {
|
fn (v &V) generate_hot_reload_code() {
|
||||||
mut cgen := v.cgen
|
mut cgen := v.cgen
|
||||||
|
|
||||||
|
@ -63,7 +88,16 @@ fn (v &V) generate_hot_reload_code() {
|
||||||
debug = '-debug'
|
debug = '-debug'
|
||||||
}
|
}
|
||||||
|
|
||||||
os.system('$vexe $msvc $debug -o $file_base -shared $file')
|
cmd_compile_shared_library := '$vexe $msvc $debug -o $file_base -shared $file'
|
||||||
|
if v.pref.show_c_cmd {
|
||||||
|
println(cmd_compile_shared_library)
|
||||||
|
}
|
||||||
|
ticks := time.ticks()
|
||||||
|
os.system(cmd_compile_shared_library)
|
||||||
|
diff := time.ticks() - ticks
|
||||||
|
println('compiling shared library took $diff ms')
|
||||||
|
println('=========\n')
|
||||||
|
|
||||||
cgen.genln('
|
cgen.genln('
|
||||||
|
|
||||||
void lfnmutex_print(char *s){
|
void lfnmutex_print(char *s){
|
||||||
|
|
|
@ -368,7 +368,7 @@ fn (v mut V) compile() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$if js {
|
$if js {
|
||||||
cgen.genln('main();')
|
cgen.genln('main__main();')
|
||||||
}
|
}
|
||||||
cgen.save()
|
cgen.save()
|
||||||
v.cc()
|
v.cc()
|
||||||
|
@ -439,35 +439,53 @@ string _STR_TMP(const char *fmt, ...) {
|
||||||
// It can be skipped in single file programs
|
// It can be skipped in single file programs
|
||||||
if v.pref.is_script {
|
if v.pref.is_script {
|
||||||
//println('Generating main()...')
|
//println('Generating main()...')
|
||||||
cgen.genln('int main() { init_consts();')
|
v.gen_main_start(true)
|
||||||
cgen.genln('$cgen.fn_main;')
|
cgen.genln('$cgen.fn_main;')
|
||||||
cgen.genln('return 0; }')
|
v.gen_main_end('return 0')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
println('panic: function `main` is undeclared in the main module')
|
verror('function `main` is not declared in the main module')
|
||||||
exit(1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if v.pref.is_test {
|
else if v.pref.is_test {
|
||||||
if v.table.main_exists() {
|
if v.table.main_exists() {
|
||||||
verror('test files cannot have function `main`')
|
verror('test files cannot have function `main`')
|
||||||
}
|
}
|
||||||
// make sure there's at least on test function
|
|
||||||
if !v.table.has_at_least_one_test_fn() {
|
if !v.table.has_at_least_one_test_fn() {
|
||||||
verror('test files need to have at least one test function')
|
verror('test files need to have at least one test function')
|
||||||
}
|
}
|
||||||
// Generate `main` which calls every single test function
|
// Generate a C `main`, which calls every single test function
|
||||||
cgen.genln('int main() { init_consts();')
|
v.gen_main_start(false)
|
||||||
for _, f in v.table.fns {
|
for _, f in v.table.fns {
|
||||||
if f.name.starts_with('test_') {
|
if f.name.starts_with('main__test_') {
|
||||||
cgen.genln('$f.name();')
|
cgen.genln('$f.name();')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cgen.genln('return g_test_ok == 0; }')
|
v.gen_main_end('return g_test_ok == 0')
|
||||||
|
}
|
||||||
|
else if v.table.main_exists() {
|
||||||
|
v.gen_main_start(true)
|
||||||
|
cgen.genln(' main__main();')
|
||||||
|
v.gen_main_end('return 0')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (v mut V) gen_main_start(add_os_args bool){
|
||||||
|
v.cgen.genln('int main(int argc, char** argv) { ')
|
||||||
|
v.cgen.genln(' init_consts();')
|
||||||
|
if add_os_args && 'os' in v.table.imports {
|
||||||
|
v.cgen.genln(' os__args = os__init_os_args(argc, (byteptr*)argv);')
|
||||||
|
}
|
||||||
|
v.generate_hotcode_reloading_main_caller()
|
||||||
|
v.cgen.genln('')
|
||||||
|
}
|
||||||
|
fn (v mut V) gen_main_end(return_statement string){
|
||||||
|
v.cgen.genln('')
|
||||||
|
v.cgen.genln(' $return_statement;')
|
||||||
|
v.cgen.genln('}')
|
||||||
|
}
|
||||||
|
|
||||||
fn final_target_out_name(out_name string) string {
|
fn final_target_out_name(out_name string) string {
|
||||||
mut cmd := if out_name.starts_with('/') {
|
mut cmd := if out_name.starts_with('/') {
|
||||||
out_name
|
out_name
|
||||||
|
|
|
@ -2037,7 +2037,10 @@ fn (p mut Parser) dot(str_typ string, method_ph int) string {
|
||||||
// field
|
// field
|
||||||
if has_field {
|
if has_field {
|
||||||
struct_field := if typ.name != 'Option' { p.table.var_cgen_name(field_name) } else { field_name }
|
struct_field := if typ.name != 'Option' { p.table.var_cgen_name(field_name) } else { field_name }
|
||||||
field := p.table.find_field(typ, struct_field) or { panic('field') }
|
field := p.table.find_field(typ, struct_field) or {
|
||||||
|
p.error('missing field: $struct_field in type $typ.name')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
if !field.is_mut && !p.has_immutable_field {
|
if !field.is_mut && !p.has_immutable_field {
|
||||||
p.has_immutable_field = true
|
p.has_immutable_field = true
|
||||||
p.first_immutable_field = field
|
p.first_immutable_field = field
|
||||||
|
@ -3008,7 +3011,10 @@ fn (p mut Parser) struct_init(typ string) string {
|
||||||
if field in inited_fields {
|
if field in inited_fields {
|
||||||
p.error('already initialized field `$field` in `$t.name`')
|
p.error('already initialized field `$field` in `$t.name`')
|
||||||
}
|
}
|
||||||
f := t.find_field(field) or { panic('field') }
|
f := t.find_field(field) or {
|
||||||
|
p.error('no such field: "$field" in type $typ')
|
||||||
|
break
|
||||||
|
}
|
||||||
inited_fields << field
|
inited_fields << field
|
||||||
p.gen_struct_field_init(field)
|
p.gen_struct_field_init(field)
|
||||||
p.check(.colon)
|
p.check(.colon)
|
||||||
|
@ -3774,23 +3780,35 @@ fn (p &Parser) prepend_mod(name string) string {
|
||||||
|
|
||||||
fn (p mut Parser) go_statement() {
|
fn (p mut Parser) go_statement() {
|
||||||
p.check(.key_go)
|
p.check(.key_go)
|
||||||
|
mut gopos := p.scanner.get_scanner_pos()
|
||||||
// TODO copypasta of name_expr() ?
|
// TODO copypasta of name_expr() ?
|
||||||
// Method
|
|
||||||
if p.peek() == .dot {
|
if p.peek() == .dot {
|
||||||
|
// Method
|
||||||
var_name := p.lit
|
var_name := p.lit
|
||||||
v := p.find_var(var_name) or { return }
|
v := p.find_var(var_name) or {
|
||||||
|
return
|
||||||
|
}
|
||||||
p.mark_var_used(v)
|
p.mark_var_used(v)
|
||||||
|
gopos = p.scanner.get_scanner_pos()
|
||||||
p.next()
|
p.next()
|
||||||
p.check(.dot)
|
p.check(.dot)
|
||||||
typ := p.table.find_type(v.typ)
|
typ := p.table.find_type(v.typ)
|
||||||
method := p.table.find_method(typ, p.lit) or { panic('go method') }
|
method := p.table.find_method(typ, p.lit) or {
|
||||||
|
p.error_with_position('go method missing $var_name', gopos)
|
||||||
|
return
|
||||||
|
}
|
||||||
p.async_fn_call(method, 0, var_name, v.typ)
|
p.async_fn_call(method, 0, var_name, v.typ)
|
||||||
}
|
}
|
||||||
// Normal function
|
|
||||||
else {
|
else {
|
||||||
f := p.table.find_fn(p.lit) or { panic('fn') }
|
f_name := p.lit
|
||||||
|
// Normal function
|
||||||
|
f := p.table.find_fn(p.prepend_mod(f_name)) or {
|
||||||
|
println( p.table.debug_fns() )
|
||||||
|
p.error_with_position('can not find function $f_name', gopos)
|
||||||
|
return
|
||||||
|
}
|
||||||
if f.name == 'println' || f.name == 'print' {
|
if f.name == 'println' || f.name == 'print' {
|
||||||
p.error('`go` cannot be used with `println`')
|
p.error_with_position('`go` cannot be used with `println`', gopos)
|
||||||
}
|
}
|
||||||
p.async_fn_call(f, 0, '', '')
|
p.async_fn_call(f, 0, '', '')
|
||||||
}
|
}
|
||||||
|
|
|
@ -645,6 +645,17 @@ fn (s &Scanner) error_with_col(msg string, col int) {
|
||||||
column := col-1
|
column := col-1
|
||||||
linestart := s.find_current_line_start_position()
|
linestart := s.find_current_line_start_position()
|
||||||
lineend := s.find_current_line_end_position()
|
lineend := s.find_current_line_end_position()
|
||||||
|
|
||||||
|
fullpath := os.realpath( s.file_path )
|
||||||
|
// The filepath:line:col: format is the default C compiler
|
||||||
|
// error output format. It allows editors and IDE's like
|
||||||
|
// emacs to quickly find the errors in the output
|
||||||
|
// and jump to their source with a keyboard shortcut.
|
||||||
|
// Using only the filename leads to inability of IDE/editors
|
||||||
|
// to find the source file, when it is in another folder.
|
||||||
|
//println('${s.file_path}:${s.line_nr + 1}:${column+1}: $msg')
|
||||||
|
println('${fullpath}:${s.line_nr + 1}:${column+1}: $msg')
|
||||||
|
|
||||||
if s.should_print_line_on_error && lineend > linestart {
|
if s.should_print_line_on_error && lineend > linestart {
|
||||||
line := s.text.substr( linestart, lineend )
|
line := s.text.substr( linestart, lineend )
|
||||||
// The pointerline should have the same spaces/tabs as the offending
|
// The pointerline should have the same spaces/tabs as the offending
|
||||||
|
@ -661,16 +672,7 @@ fn (s &Scanner) error_with_col(msg string, col int) {
|
||||||
println(line)
|
println(line)
|
||||||
println(pointerline)
|
println(pointerline)
|
||||||
}
|
}
|
||||||
fullpath := os.realpath( s.file_path )
|
|
||||||
_ = fullpath
|
|
||||||
// The filepath:line:col: format is the default C compiler
|
|
||||||
// error output format. It allows editors and IDE's like
|
|
||||||
// emacs to quickly find the errors in the output
|
|
||||||
// and jump to their source with a keyboard shortcut.
|
|
||||||
// Using only the filename leads to inability of IDE/editors
|
|
||||||
// to find the source file, when it is in another folder.
|
|
||||||
//println('${s.file_path}:${s.line_nr + 1}:${column+1}: $msg')
|
|
||||||
println('${fullpath}:${s.line_nr + 1}:${column+1}: $msg')
|
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -698,7 +698,7 @@ fn (table &Table) is_interface(name string) bool {
|
||||||
// Do we have fn main()?
|
// Do we have fn main()?
|
||||||
fn (t &Table) main_exists() bool {
|
fn (t &Table) main_exists() bool {
|
||||||
for _, f in t.fns {
|
for _, f in t.fns {
|
||||||
if f.name == 'main' {
|
if f.name == 'main__main' {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -707,7 +707,7 @@ fn (t &Table) main_exists() bool {
|
||||||
|
|
||||||
fn (t &Table) has_at_least_one_test_fn() bool {
|
fn (t &Table) has_at_least_one_test_fn() bool {
|
||||||
for _, f in t.fns {
|
for _, f in t.fns {
|
||||||
if f.name.starts_with('test_') {
|
if f.name.starts_with('main__test_') {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,8 @@ import gx
|
||||||
import gg
|
import gg
|
||||||
import time
|
import time
|
||||||
import glfw
|
import glfw
|
||||||
// import math
|
import math
|
||||||
|
import os
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Size = 700
|
Size = 700
|
||||||
|
@ -16,6 +17,7 @@ struct Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
os.clear()
|
||||||
glfw.init()
|
glfw.init()
|
||||||
ctx:= &Context{
|
ctx:= &Context{
|
||||||
gg: gg.new_context(gg.Cfg {
|
gg: gg.new_context(gg.Cfg {
|
||||||
|
@ -41,10 +43,11 @@ fn (ctx &Context) draw() {
|
||||||
ctx.gg.draw_line(0, Size / 2, Size, Size / 2) // x axis
|
ctx.gg.draw_line(0, Size / 2, Size, Size / 2) // x axis
|
||||||
ctx.gg.draw_line(Size / 2, 0, Size / 2, Size) // y axis
|
ctx.gg.draw_line(Size / 2, 0, Size / 2, Size) // y axis
|
||||||
center := f64(Size / 2)
|
center := f64(Size / 2)
|
||||||
|
mut y := 0.0
|
||||||
for x := -10.0; x <= 10.0; x += 0.002 {
|
for x := -10.0; x <= 10.0; x += 0.002 {
|
||||||
y := x * x - 1
|
y = x * x - 1
|
||||||
//y := (x + 3) * (x + 3) - 1
|
//y = (x + 3) * (x + 3) - 1
|
||||||
//y := math.sqrt(30.0 - x * x)
|
//y = math.sqrt(30.0 - x * x)
|
||||||
ctx.gg.draw_rect(center + x * Scale, center - y * Scale, 1, 1, gx.Black)
|
ctx.gg.draw_rect(center + x * Scale, center - y * Scale, 1, 1, gx.Black)
|
||||||
//ctx.gg.draw_rect(center + x * Scale, center + y * Scale, 1, 1, gx.Black)
|
//ctx.gg.draw_rect(center + x * Scale, center + y * Scale, 1, 1, gx.Black)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// v -live message.v
|
// v -live message.v
|
||||||
module main
|
module main
|
||||||
|
|
||||||
|
import os
|
||||||
import time
|
import time
|
||||||
|
|
||||||
[live]
|
[live]
|
||||||
|
@ -10,6 +11,7 @@ fn print_message() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
os.clear()
|
||||||
for {
|
for {
|
||||||
print_message()
|
print_message()
|
||||||
time.sleep_ms(500)
|
time.sleep_ms(500)
|
||||||
|
|
Loading…
Reference in New Issue