jsgen: class -> factory
parent
1633675c11
commit
f2ea8ca62c
|
@ -7,10 +7,10 @@ module builtin
|
|||
fn JS.console.log(arg ...string)
|
||||
fn JS.process.stdout.write(arg string)
|
||||
|
||||
pub fn println(s string) {
|
||||
pub fn println(s any) {
|
||||
JS.console.log(s)
|
||||
}
|
||||
|
||||
pub fn print(s string) {
|
||||
pub fn print(s any) {
|
||||
JS.process.stdout.write(s)
|
||||
}
|
|
@ -17,6 +17,9 @@ const (
|
|||
'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']
|
||||
type_values = {
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
struct JsGen {
|
||||
|
@ -115,7 +118,8 @@ pub fn gen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
|||
for pub_var in g.namespaces_pub[node.name] {
|
||||
out += '\n\t\t$pub_var,'
|
||||
}
|
||||
out += '\n\t};'
|
||||
if g.namespaces_pub[node.name].len > 0 { out += '\n\t' }
|
||||
out += '};'
|
||||
out += '\n})('
|
||||
for i, key in imports.keys() {
|
||||
if i > 0 { out += ', ' }
|
||||
|
@ -242,7 +246,7 @@ fn (mut g JsGen) to_js_typ(typ string) string {
|
|||
styp = g.to_js_typ(typ.replace('array_', '')) + '[]'
|
||||
} else if typ.starts_with('map_') {
|
||||
tokens := typ.split('_')
|
||||
styp = 'Map<${tokens[1]}, ${tokens[2]}>'
|
||||
styp = 'Map<${g.to_js_typ(tokens[1])}, ${g.to_js_typ(tokens[2])}>'
|
||||
} else {
|
||||
styp = typ
|
||||
}
|
||||
|
@ -259,6 +263,42 @@ fn (mut g JsGen) to_js_typ(typ string) string {
|
|||
return styp
|
||||
}
|
||||
|
||||
fn (mut g JsGen) to_js_typ_val(typ string) string {
|
||||
mut styp := ''
|
||||
match typ {
|
||||
'number' {
|
||||
styp = '0'
|
||||
}
|
||||
'boolean' {
|
||||
styp = 'false'
|
||||
}
|
||||
'Object' {
|
||||
styp = '{}'
|
||||
}
|
||||
'string' {
|
||||
styp = '""'
|
||||
}
|
||||
else {
|
||||
if typ.starts_with('Map') {
|
||||
styp = 'new Map()'
|
||||
} else if typ.ends_with('[]') {
|
||||
styp = '[]'
|
||||
} else {
|
||||
styp = '{}'
|
||||
}
|
||||
}
|
||||
}
|
||||
// ns.export => ns["export"]
|
||||
for i, v in styp.split('.') {
|
||||
if i == 0 {
|
||||
styp = v
|
||||
continue
|
||||
}
|
||||
styp += '["$v"]'
|
||||
}
|
||||
return styp
|
||||
}
|
||||
|
||||
pub fn (g &JsGen) save() {}
|
||||
|
||||
pub fn (mut g JsGen) gen_indent() {
|
||||
|
@ -828,7 +868,7 @@ fn (mut g JsGen) gen_method_decl(it ast.FnDecl) {
|
|||
if is_main {
|
||||
g.write(')();')
|
||||
}
|
||||
if !it.is_anon {
|
||||
if !it.is_anon && !it.is_method {
|
||||
g.writeln('')
|
||||
}
|
||||
|
||||
|
@ -1021,27 +1061,44 @@ fn (mut g JsGen) enum_expr(node ast.Expr) {
|
|||
}
|
||||
|
||||
fn (mut g JsGen) gen_struct_decl(node ast.StructDecl) {
|
||||
g.writeln('class ${g.js_name(node.name)} {')
|
||||
g.inc_indent()
|
||||
g.writeln(g.doc.gen_ctor(node.fields))
|
||||
g.writeln('constructor(values) {')
|
||||
g.writeln(g.doc.gen_fac_fn(node.fields))
|
||||
g.write('function ${g.js_name(node.name)}({ ')
|
||||
for i, field in node.fields {
|
||||
g.write('$field.name = ')
|
||||
if field.has_default_expr {
|
||||
g.expr(field.default_expr)
|
||||
} else {
|
||||
g.write('${g.to_js_typ_val(g.typ(field.typ))}')
|
||||
}
|
||||
if i < node.fields.len - 1 { g.write(', ') }
|
||||
}
|
||||
g.writeln(' }) {')
|
||||
g.inc_indent()
|
||||
for field in node.fields {
|
||||
// TODO: Generate default struct init values
|
||||
g.writeln('this.$field.name = values.$field.name')
|
||||
g.writeln('this.$field.name = $field.name')
|
||||
}
|
||||
g.dec_indent()
|
||||
g.writeln('}')
|
||||
g.writeln('};')
|
||||
|
||||
g.writeln('${g.js_name(node.name)}.prototype = {')
|
||||
g.inc_indent()
|
||||
|
||||
fns := g.method_fn_decls[node.name]
|
||||
for cfn in fns {
|
||||
|
||||
for i, field in node.fields {
|
||||
g.writeln(g.doc.gen_typ(g.typ(field.typ), field.name))
|
||||
g.write('$field.name: ${g.to_js_typ_val(g.typ(field.typ))}')
|
||||
if i < node.fields.len - 1 || fns.len > 0 { g.writeln(',') } else { g.writeln('') }
|
||||
}
|
||||
|
||||
for i, cfn in fns {
|
||||
// TODO: Move cast to the entire array whenever it's possible
|
||||
it := cfn as ast.FnDecl
|
||||
g.writeln('')
|
||||
g.gen_method_decl(it)
|
||||
if i < fns.len - 1 { g.writeln(',') } else { g.writeln('') }
|
||||
}
|
||||
g.dec_indent()
|
||||
g.writeln('}\n')
|
||||
g.writeln('};\n')
|
||||
if node.is_pub {
|
||||
g.push_pub_var(node.name)
|
||||
}
|
||||
|
@ -1050,18 +1107,22 @@ fn (mut g JsGen) gen_struct_decl(node ast.StructDecl) {
|
|||
fn (mut g JsGen) gen_struct_init(it ast.StructInit) {
|
||||
type_sym := g.table.get_type_symbol(it.typ)
|
||||
name := type_sym.name
|
||||
g.writeln('new ${g.js_name(name)}({')
|
||||
g.inc_indent()
|
||||
for i, field in it.fields {
|
||||
g.write('$field.name: ')
|
||||
g.expr(field.expr)
|
||||
if i < it.fields.len - 1 {
|
||||
g.write(', ')
|
||||
if it.fields.len == 0 {
|
||||
g.write('new ${g.js_name(name)}({})')
|
||||
} else {
|
||||
g.writeln('new ${g.js_name(name)}({')
|
||||
g.inc_indent()
|
||||
for i, field in it.fields {
|
||||
g.write('$field.name: ')
|
||||
g.expr(field.expr)
|
||||
if i < it.fields.len - 1 {
|
||||
g.write(', ')
|
||||
}
|
||||
g.writeln('')
|
||||
}
|
||||
g.writeln('')
|
||||
g.dec_indent()
|
||||
g.write('})')
|
||||
}
|
||||
g.dec_indent()
|
||||
g.write('})')
|
||||
}
|
||||
|
||||
fn (mut g JsGen) gen_ident(node ast.Ident) {
|
||||
|
|
|
@ -53,7 +53,7 @@ fn (mut d JsDoc) gen_typ(typ, name string) string {
|
|||
return d.out.str()
|
||||
}
|
||||
|
||||
fn (mut d JsDoc) gen_ctor(fields []ast.StructField) string {
|
||||
fn (mut d JsDoc) gen_fac_fn(fields []ast.StructField) string {
|
||||
d.reset()
|
||||
d.writeln('/**')
|
||||
d.write(' * @param {{')
|
||||
|
@ -62,9 +62,7 @@ fn (mut d JsDoc) gen_ctor(fields []ast.StructField) string {
|
|||
// so all struct members don't have to be initialized.
|
||||
// TODO: Actually generate default struct init values :P
|
||||
d.write('$field.name?: ${d.gen.typ(field.typ)}')
|
||||
if i < fields.len - 1 {
|
||||
d.write(', ')
|
||||
}
|
||||
if i < fields.len - 1 { d.write(', ') }
|
||||
}
|
||||
d.writeln('}} values - values for this class fields')
|
||||
d.writeln(' * @constructor')
|
||||
|
@ -93,6 +91,7 @@ fn (mut d JsDoc) gen_fn(it ast.FnDecl) string {
|
|||
}
|
||||
}
|
||||
d.writeln(' * @returns {$type_name}')
|
||||
d.writeln(' * @function')
|
||||
d.write('*/')
|
||||
return d.out.str()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
// V_COMMIT_HASH 7e55261
|
||||
// V_CURRENT_COMMIT_HASH 79b1f27
|
||||
// Generated by the V compiler
|
||||
|
||||
"use strict";
|
||||
|
||||
/** @namespace builtin */
|
||||
const builtin = (function () {
|
||||
/**
|
||||
* @param {any} s
|
||||
* @returns {void}
|
||||
* @function
|
||||
*/
|
||||
function println(s) {
|
||||
console.log(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} s
|
||||
* @returns {void}
|
||||
* @function
|
||||
*/
|
||||
function print(s) {
|
||||
process.stdout.write(s);
|
||||
}
|
||||
|
||||
/* module exports */
|
||||
return {
|
||||
println,
|
||||
print,
|
||||
};
|
||||
})();
|
||||
|
||||
/** @namespace main */
|
||||
const main = (function () {
|
||||
/**
|
||||
* @param {{value?: number, test?: Map<string, number>, hello?: number[]}} values - values for this class fields
|
||||
* @constructor
|
||||
*/
|
||||
function Int({ value = 0, test = new Map(), hello = [] }) {
|
||||
this.value = value
|
||||
this.test = test
|
||||
this.hello = hello
|
||||
};
|
||||
Int.prototype = {
|
||||
/** @type {number} - value */
|
||||
value: 0,
|
||||
/** @type {Map<string, number>} - test */
|
||||
test: new Map(),
|
||||
/** @type {number[]} - hello */
|
||||
hello: [],
|
||||
/**
|
||||
* @param {number} value
|
||||
* @returns {void}
|
||||
* @function
|
||||
*/
|
||||
add(value) {
|
||||
const i = this;
|
||||
i.value += value;
|
||||
},
|
||||
/**
|
||||
* @returns {number}
|
||||
* @function
|
||||
*/
|
||||
get() {
|
||||
const i = this;
|
||||
return i.value;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* program entry point */
|
||||
(function() {
|
||||
const a = new Int({
|
||||
value: 10
|
||||
});
|
||||
a.add(5);
|
||||
builtin.println(a);
|
||||
const b = new Int({});
|
||||
b.add(10);
|
||||
builtin.println(b.get());
|
||||
})();
|
||||
|
||||
/* module exports */
|
||||
return {};
|
||||
})();
|
||||
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
module main
|
||||
|
||||
struct Int {
|
||||
mut:
|
||||
value int
|
||||
test map[string]int
|
||||
hello []int
|
||||
}
|
||||
|
||||
fn (mut i Int) add(value int) {
|
||||
i.value += value
|
||||
}
|
||||
|
||||
fn (i Int) get() int {
|
||||
return i.value
|
||||
}
|
||||
|
||||
fn main() {
|
||||
a := Int { value: 10 }
|
||||
a.add(5)
|
||||
println(a) // 15
|
||||
|
||||
b := Int{}
|
||||
b.add(10)
|
||||
println(b.get()) // 10
|
||||
}
|
Loading…
Reference in New Issue