diff --git a/vlib/builtin/js/array.v b/vlib/builtin/js/array.v deleted file mode 100644 index 6c9afda12d..0000000000 --- a/vlib/builtin/js/array.v +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved. -// Use of this source code is governed by an MIT license -// that can be found in the LICENSE file. - -module builtin - -import strings - -pub struct array { -pub: - data voidptr - len int - cap int - element_size int -} - -/* -// Private function, used by V (`nums := []int{}`) -fn new_array(mylen, cap, elm_size int) array { - arr := array { - len: mylen - cap: cap - element_size: elm_size - } - return arr -} - - -// TODO -pub fn _make(len, cap, elm_size int) array { - return new_array(len, cap, elm_size) -} - - -*/ - -pub fn make(len, cap, elm_size int) array { - return array{} -} - -fn array_repeat(val voidptr, nr_repeats, elm_size int) array { - return val -} - -pub fn (a array) repeat(nr_repeats int) array { - #return Array(a[0]).fill(nr_repeats) - return a -} - -pub fn (mut a array) sort_with_compare(compare voidptr) { -} - -pub fn (mut a array) insert(i int, val voidptr) { -} - -pub fn (mut a array) prepend(val voidptr) { - a.insert(0, val) -} - -pub fn (mut a array) delete_elm(idx int) { -} - -/* -pub fn (a array) first() voidptr { - if a.len == 0 { - panic('array.first: empty array') - } - return a.data + 0 -} - -pub fn (a array) last() voidptr { - if a.len == 0 { - panic('array.last: empty array') - } - return a.data + (a.len - 1) * a.element_size -} -*/ - -pub fn (s array) left(n int) array { - if n >= s.len { - return s - } - return s.slice(0, n) -} - -pub fn (s array) right(n int) array { - if n >= s.len { - return s - } - return s.slice(n, s.len) -} - -pub fn (s array) slice(start, _end int) array { - return s -} - -pub fn (a array) reverse() array { - return a -} - -// array.clone_static returns an independent copy of a given array -// It should be used only in -autofree generated code. -fn (a array) clone_static() array { - return a.clone() -} - -pub fn (a array) clone() array { - return a -} - -pub fn (a &array) free() { -} - -// "[ 'a', 'b', 'c' ]" -pub fn (a []string) str() string { - mut sb := strings.new_builder(a.len * 3) - sb.write('[') - for i in 0..a.len { - val := a[i] - sb.write('"') - sb.write(val) - sb.write('"') - if i < a.len - 1 { - sb.write(', ') - } - } - sb.write(']') - return sb.str() -} - -pub fn (b []byte) hex() string { - return 'sdf' -} - -pub fn (mut arr array) push_many(val voidptr, size int) { -} - -pub fn free(voidptr) { - -} diff --git a/vlib/builtin/js/builtin.v b/vlib/builtin/js/builtin.v index 7fb5e0ee32..2ee5f6ff3e 100644 --- a/vlib/builtin/js/builtin.v +++ b/vlib/builtin/js/builtin.v @@ -4,32 +4,13 @@ module builtin -pub fn exit(code int) { - println('js.exit()') -} - -// isnil returns true if an object is nil (only for C objects). -pub fn isnil(v voidptr) bool { - return v == 0 -} - -pub fn panic(s string) { - eprintln('V panic: ' + s) - exit(1) -} +fn JS.console.log(arg ...string) +fn JS.process.stdout.write(arg string) pub fn println(s string) { - #console.log(s.str) -} - -pub fn eprintln(s string) { - #console.error(s) + JS.console.log(s) } pub fn print(s string) { - #console.log(s) -} - - - - + JS.process.stdout.write(s) +} \ No newline at end of file diff --git a/vlib/builtin/js/hashmap.v b/vlib/builtin/js/hashmap.v deleted file mode 100644 index a9e31a4939..0000000000 --- a/vlib/builtin/js/hashmap.v +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved. -// Use of this source code is governed by an MIT license -// that can be found in the LICENSE file. - -module builtin - -/* -TODO: Implement hashmap for js when hashmap for V is done. -*/ - -fn foo() { - -} diff --git a/vlib/builtin/js/int.v b/vlib/builtin/js/int.v deleted file mode 100644 index f1affe00da..0000000000 --- a/vlib/builtin/js/int.v +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved. -// Use of this source code is governed by an MIT license -// that can be found in the LICENSE file. - -module builtin - -#include -#include - - -pub fn (d f64) str() string { - return '0' -} - -pub fn (d f32) str() string { - return '0' -} - -pub fn ptr_str(ptr voidptr) string { - return '0' -} - -// compare floats using C epsilon -pub fn (a f64) eq(b f64) bool { - //return C.fabs(a - b) <= C.DBL_EPSILON - return (a - b) <= 0.01 -} - -// fn (nn i32) str() string { -// return i -// } -pub fn (nn int) str() string { - return '0' -} - -pub fn (nn u32) str() string { - return '0' -} - -pub fn (nn i64) str() string { - return '0' -} - -pub fn (nn u64) str() string { - return '0' -} - -pub fn (b bool) str() string { - if b { - return 'true' - } - return 'false' -} - -pub fn (n int) hex() string { - return '0' -} - -pub fn (n i64) hex() string { - return '0' -} - -pub fn (a []byte) contains(val byte) bool { - for aa in a { - if aa == val { - return true - } - } - return false -} - -pub fn (c rune) str() string { - return '0' -} - -pub fn (c byte) str() string { - return '0' -} - -pub fn (c byte) is_capital() bool { - return c >= `A` && c <= `Z` -} - -pub fn (b []byte) clone() []byte { - mut res := [byte(0)].repeat(b.len) - for i in 0..b.len { - res[i] = b[i] - } - return res -} - - diff --git a/vlib/builtin/js/map.v b/vlib/builtin/js/map.v deleted file mode 100644 index 6ea2979870..0000000000 --- a/vlib/builtin/js/map.v +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved. -// Use of this source code is governed by an MIT license -// that can be found in the LICENSE file. - -module builtin - -import strings - -pub struct map { - obj voidptr -} - -//fn (mut m map) insert(n mut mapnode, key string, val voidptr) { -//} - -//////fn (n & mapnode) find(key string, out voidptr, element_size int) bool{ - //return false -//} - -// same as `find`, but doesn't return a value. Used by `exists` -//fn (n & mapnode) find2(key string, element_size int) bool{ - //return false -//} - -//fn preorder_keys(node &mapnode, keys mut []string, key_i int) int { - //return 0 -//} - -pub fn (mut m map) keys() []string { - return [''] -} - -fn (m map) get(key string, out voidptr) bool { - return false -} - -pub fn (mut m map) delete(key string) { -} - -fn (m map) exists(key string) bool { - return false -} - -pub fn (m map) print() { - println('<<<<<<<<') - println('>>>>>>>>>>') -} - -pub fn (m map) free() { - // C.free(m.table) - // C.free(m.keys_table) -} - -pub fn (m map_string) str() string { - /* - if m.size == 0 { - return '{}' - } - */ - mut sb := strings.new_builder(50) - sb.writeln('{') - for key, val in m { - //sb.writeln(' "$key" => "$val"') - } - sb.writeln('}') - return sb.str() -} diff --git a/vlib/builtin/js/option.v b/vlib/builtin/js/option.v deleted file mode 100644 index 86aa638160..0000000000 --- a/vlib/builtin/js/option.v +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved. -// Use of this source code is governed by an MIT license -// that can be found in the LICENSE file. - -module builtin - -struct Option { - data [255]byte - error string - ok bool -} - -// `fn foo() ?Foo { return foo }` => `fn foo() ?Foo { return opt_ok(foo); }` -fn opt_ok(data voidptr, size int) Option { - if size >= 255 { - panic('option size too big') - } - res := Option { - ok: true - } - C.memcpy(res.data, data, size) - return res -} - -pub fn error(s string) Option { - return Option { - error: s - } -} - - diff --git a/vlib/builtin/js/string.v b/vlib/builtin/js/string.v deleted file mode 100644 index 01306a2173..0000000000 --- a/vlib/builtin/js/string.v +++ /dev/null @@ -1,319 +0,0 @@ -// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved. -// Use of this source code is governed by an MIT license -// that can be found in the LICENSE file. - -module builtin - -pub struct string { -//mut: - //hash_cache int -pub: - str byteptr - len int -} - -// For C strings only -fn C.strlen(s byteptr) int - -fn todo() { } - -pub fn tos(s byteptr) string { - len := 0 - #len = s.length; - return string{ - str: s - len: len - } -} - -// string.clone_static returns an independent copy of a given array -// It should be used only in -autofree generated code. -fn (a string) clone_static() string { - return a.clone() -} - -pub fn (a string) clone() string { - return a -} - -pub fn (s string) replace(rep, with_ string) string { - return s -} - -pub fn (s string) int() int { - return 0 -} - -pub fn (s string) i64() i64 { - return 0 -} - -pub fn (s string) f32() f32 { - return 0.0 -} - -pub fn (s string) f64() f64 { - return 0.0 -} - -pub fn (s string) u32() u32 { - return u32(0) -} - -pub fn (s string) u64() u64 { - return u64(0) -} - -pub fn (s string) split(delim string) []string { - return s.split(delim) -} - -pub fn (s string) split_into_lines() []string { - return s.split('\n') -} - -// 'hello'.left(2) => 'he' -pub fn (s string) left(n int) string { - if n >= s.len { - return s - } - return s.substr(0, n) -} -// 'hello'.right(2) => 'llo' -pub fn (s string) right(n int) string { - if n >= s.len { - return '' - } - return s.substr(n, s.len) -} - -pub fn (s string) substr(start, end int) string { - return 'a' -} - -pub fn (s string) index(p string) int { - return -1 -} - -pub fn (s string) index_any(chars string) int { - return -1 -} - -pub fn (s string) last_index(p string) int { - return -1 -} - -pub fn (s string) index_after(p string, start int) int { - return -1 -} - -// counts occurrences of substr in s -pub fn (s string) count(substr string) int { - return 0 // TODO can never get here - v doesn't know that -} - -pub fn (s string) contains(p string) bool { - return false -} - -pub fn (s string) starts_with(p string) bool { - return false -} - -pub fn (s string) ends_with(p string) bool { - return false -} - -// TODO only works with ASCII -pub fn (s string) to_lower() string { - return s -} - -pub fn (s string) to_upper() string { - return s -} - -pub fn (s string) capitalize() string { - return s -} - -pub fn (s string) title() string { - return s -} - -// 'hey [man] how you doin' -// find_between('[', ']') == 'man' -pub fn (s string) find_between(start, end string) string { - start_pos := s.index(start) - if start_pos == -1 { - return '' - } - // First get everything to the right of 'start' - val := s[start_pos + start.len..] - end_pos := val.index(end) - if end_pos == -1 { - return val - } - return val[..end_pos] -} - -// TODO generic -pub fn (ar []string) contains(val string) bool { - for s in ar { - if s == val { - return true - } - } - return false -} - -// TODO generic -pub fn (ar []int) contains(val int) bool { - for i, s in ar { - if s == val { - return true - } - } - return false -} - - -fn is_space(c byte) bool { - return C.isspace(c) -} - -pub fn (c byte) is_space() bool { - return is_space(c) -} - -pub fn (s string) trim_space() string { - #return s.str.trim(' '); - return '' -} - -pub fn (s string) trim(cutset string) string { - #return s.str.trim(cutset); - return '' -} - -pub fn (s string) trim_left(cutset string) string { - #return s.str.trimLeft(cutset); - return '' -} - -pub fn (s string) trim_right(cutset string) string { - #return s.str.trimRight(cutset); - return '' -} - -// fn print_cur_thread() { -// //C.printf("tid = %08x \n", pthread_self()); -// } -pub fn (mut s []string) sort() { - -} - -pub fn (mut s []string) sort_ignore_case() { -} - -pub fn (mut s []string) sort_by_len() { -} - -fn (s string) at(idx int) byte { - if idx < 0 || idx >= s.len { - panic('string index out of range') - } - return s.str[idx] -} - -pub fn (c byte) is_digit() bool { - return c >= `0` && c <= `9` -} - -pub fn (c byte) is_hex_digit() bool { - return c.is_digit() || (c >= `a` && c <= `f`) || (c >= `A` && c <= `F`) -} - -pub fn (c byte) is_oct_digit() bool { - return c >= `0` && c <= `7` -} - -pub fn (c byte) is_bin_digit() bool { - return c == `0` || c == `1` -} - -pub fn (c byte) is_letter() bool { - return (c >= `a` && c <= `z`) || (c >= `A` && c <= `Z`) -} - -pub fn (s &string) free() { -} - -// all_before('23:34:45.234', '.') == '23:34:45' -pub fn (s string) all_before(dot string) string { - pos := s.index(dot) - if pos == -1 { - return s - } - return s[..pos] -} - -pub fn (s string) all_before_last(dot string) string { - pos := s.last_index(dot) - if pos == -1 { - return s - } - return s[..pos] -} - -pub fn (s string) all_after(dot string) string { - pos := s.last_index(dot) - if pos == -1 { - return s - } - return s[pos + dot.len..] -} - -// fn (s []string) substr(a, b int) string { -// return join_strings(s.slice_fast(a, b)) -// } -pub fn (a []string) join(del string) string { - return '' -} - -pub fn (s []string) join_lines() string { - return s.join('\n') -} - -pub fn (s string) reverse() string { - return s -} - -pub fn (s string) limit(max int) string { - if s.len <= max { - return s - } - return s.substr(0, max) -} - -// TODO is_white_space() -pub fn (c byte) is_white() bool { - i := int(c) - return i == 10 || i == 32 || i == 9 || i == 13 || c == `\r` -} - - -pub fn (s string) hash() int { - //mut h := s.hash_cache - mut h := 0 - if h == 0 && s.len > 0 { - for c in s { - h = h * 31 + int(c) - } - } - return h -} - -pub fn (s string) bytes() []byte { - return [] -} diff --git a/vlib/builtin/js/utf8.v b/vlib/builtin/js/utf8.v deleted file mode 100644 index fc5207e328..0000000000 --- a/vlib/builtin/js/utf8.v +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved. -// Use of this source code is governed by an MIT license -// that can be found in the LICENSE file. - -module builtin - -pub fn utf8_char_len(b byte) int { - return (( 0xe5000000 >> (( b >> 3 ) & 0x1e )) & 3 ) + 1 -} - -// Convert utf32 to utf8 -// utf32 == Codepoint -pub fn utf32_to_str(code u32) string { - return '' -} - -// TODO copypasta -pub fn utf32_to_str_no_malloc(code u32, buf voidptr) string { - return '' -} - -// Convert utf8 to utf32 -pub fn (_rune string) utf32_code() int { - return 0 -} - - diff --git a/vlib/v/builder/compile.v b/vlib/v/builder/compile.v index 61d9d34a88..cf1d8173fc 100644 --- a/vlib/v/builder/compile.v +++ b/vlib/v/builder/compile.v @@ -59,7 +59,12 @@ fn (mut b Builder) run_compiled_executable_and_exit() { if b.pref.is_verbose { println('============ running $b.pref.out_name ============') } + mut cmd := '"${b.pref.out_name}"' + + if b.pref.backend == .js { + cmd = 'node "${b.pref.out_name}.js"' + } for arg in b.pref.run_args { // Determine if there are spaces in the parameters if arg.index_byte(` `) > 0 { @@ -139,7 +144,7 @@ pub fn (v Builder) get_builtin_files() []string { if v.pref.is_bare { return v.v_files_from_dir(os.join_path(location, 'builtin', 'bare')) } - $if js { + if v.pref.backend == .js { return v.v_files_from_dir(os.join_path(location, 'builtin', 'js')) } return v.v_files_from_dir(os.join_path(location, 'builtin')) diff --git a/vlib/v/builder/js.v b/vlib/v/builder/js.v index c18342c307..715e93a0a9 100644 --- a/vlib/v/builder/js.v +++ b/vlib/v/builder/js.v @@ -38,13 +38,22 @@ pub fn (mut b Builder) build_js(v_files []string, out_file string) { } pub fn (mut b Builder) compile_js() { - // TODO files << b.get_builtin_files() - files := b.get_user_files() + mut files := b.get_user_files() + files << b.get_builtin_files() b.set_module_lookup_paths() if b.pref.is_verbose { println('all .v files:') println(files) } b.build_js(files, b.pref.out_name + '.js') - // TODO run the file } + +fn (mut b Builder) run_js() { + cmd := 'node ' + b.pref.out_name + '.js' + res := os.exec(cmd) or { + println('JS compilation failed.') + verror(err) + return + } + println(res.output) +} \ No newline at end of file diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index bf2050be99..5ea3d66c45 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -16,6 +16,7 @@ const ( 'protected', 'public', 'return', 'static', 'super', 'switch', 'this', 'throw', 'try', 'typeof', 'var', 'void', 'while', 'with', 'yield'] tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', '\t\t\t\t\t\t\t', '\t\t\t\t\t\t\t\t'] + builtin_globals = ['println', 'print'] ) struct JsGen { @@ -452,25 +453,7 @@ fn (mut g JsGen) expr(node ast.Expr) { g.write("'$it.val'") } ast.CallExpr { - mut name := '' - if it.name.starts_with('JS.') { - name = it.name[3..] - } else { - name = g.js_name(it.name) - } - g.expr(it.left) - if it.is_method { - // example: foo.bar.baz() - g.write('.') - } - g.write('${g.js_name(name)}(') - for i, arg in it.args { - g.expr(arg.expr) - if i != it.args.len - 1 { - g.write(', ') - } - } - g.write(')') + g.gen_call_expr(it) } ast.EnumVal { styp := g.typ(it.typ) @@ -1093,6 +1076,32 @@ fn (mut g JsGen) gen_ident(node ast.Ident) { g.write(name) } +fn (mut g JsGen) gen_call_expr(it ast.CallExpr) { + mut name := '' + if it.name.starts_with('JS.') { + name = it.name[3..] + } else { + name = g.js_name(it.name) + } + g.expr(it.left) + if it.is_method { + // example: foo.bar.baz() + g.write('.') + } else { + if name in builtin_globals { + g.write('builtin.') + } + } + g.write('${g.js_name(name)}(') + for i, arg in it.args { + g.expr(arg.expr) + if i != it.args.len - 1 { + g.write(', ') + } + } + g.write(')') +} + fn (mut g JsGen) gen_selector_expr(it ast.SelectorExpr) { g.expr(it.expr) g.write('.$it.field_name') diff --git a/vlib/v/gen/js/tests/simple.js b/vlib/v/gen/js/tests/simple.js index a7d189af19..2ef3a34dd3 100644 --- a/vlib/v/gen/js/tests/simple.js +++ b/vlib/v/gen/js/tests/simple.js @@ -1,105 +1,44 @@ -// V_COMMIT_HASH 74686d0 -// V_CURRENT_COMMIT_HASH 0d3f133 +// V_COMMIT_HASH 0de70e8 +// V_CURRENT_COMMIT_HASH 0de70e8 // Generated by the V compiler "use strict"; -/* namespace: hello */ -const hello = (function () { - class A { - /** - * @param {{foo?: string}} values - values for this class fields - * @constructor - */ - constructor(values) { - this.foo = values.foo - } - - /** - * @param {string} s - * @returns {void} - */ - update(s) { - const a = this; - a.foo = s; - } - } - - - class B { - /** - * @param {{}} values - values for this class fields - * @constructor - */ - constructor(values) { - } - } - - const C = Object.freeze({ - }); - +/* namespace: builtin */ +const builtin = (function () { /** - * @returns {string} + * @param {string} s + * @returns {void} */ - function v_debugger() { - const v = new B({ - }); - return "Hello"; + function println(s) { + console.log(s); } /** - * @returns {string} + * @param {string} s + * @returns {void} */ - function excited() { - return v_debugger() + "!"; + function print(s) { + process.stdout.write(s); } /* module exports */ return { - A, - C, - v_debugger, - excited, + println, + print, }; })(); /* namespace: main */ -const main = (function (hello) { - class D { - /** - * @param {{a?: hello["A"]["prototype"]}} values - values for this class fields - * @constructor - */ - constructor(values) { - this.a = values.a - } - } - - /** - * @param {hello["A"]["prototype"]} arg - * @returns {void} - */ - function struct_arg(arg) { - console.log(arg); - } - +const main = (function () { /* program entry point */ (function() { - struct_arg(new hello.A({ - foo: "hello" - })); - /** @type {number} - a */ - let a = 1; - a += 2; - console.log(a); - const b = new hello.A({ - }); - console.log(b); + builtin.println("hello world"); })(); /* module exports */ return { }; -})(hello); +})(); diff --git a/vlib/v/gen/js/tests/simple.v b/vlib/v/gen/js/tests/simple.v index e10aeebbf3..9d84af50e5 100644 --- a/vlib/v/gen/js/tests/simple.v +++ b/vlib/v/gen/js/tests/simple.v @@ -1,25 +1,5 @@ -import hello -// import hello.hello1 -// TODO: Uncomment once nested modules work - -fn JS.console.log() - -struct D { - a hello.A -} - -fn struct_arg (arg hello.A) { - JS.console.log(arg) -} +module main fn main() { - - struct_arg(hello.A{ 'hello' }) - - mut a := 1 - a += 2 - JS.console.log(a) - b := hello.A{} - JS.console.log(b) - // hello1.nested() + println("hello world") }