js: fix interfaces behaviour & disable struct deep copy for now (#12333)
parent
d33f7d12f7
commit
a32dae335a
|
@ -2,6 +2,6 @@ Drawing with mouse events using DOM API. Adopted from MDN examples.
|
||||||
|
|
||||||
# Compiling
|
# Compiling
|
||||||
```
|
```
|
||||||
v -b js_browser examples/js_dom_draw/draw.v
|
v -b js_browser examples/js_dom_draw/draw.js.v
|
||||||
```
|
```
|
||||||
Then you can open `index.html` with your favourite browser.
|
Then you can open `index.html` with your favourite browser.
|
||||||
|
|
|
@ -27,8 +27,14 @@ fn draw_line(context ctx.CanvasRenderingContext2D, x1 int, y1 int, x2 int, y2 in
|
||||||
context.close_path()
|
context.close_path()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DrawState {
|
||||||
|
mut:
|
||||||
|
drawing bool
|
||||||
|
x int
|
||||||
|
y int
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
/*
|
|
||||||
document := jsdom.document
|
document := jsdom.document
|
||||||
|
|
||||||
elem := document.get_element_by_id('myButton') ?
|
elem := document.get_element_by_id('myButton') ?
|
||||||
|
@ -36,39 +42,36 @@ fn main() {
|
||||||
canv := jsdom.get_html_canvas_element(elemc) or { panic('expected canvas') }
|
canv := jsdom.get_html_canvas_element(elemc) or { panic('expected canvas') }
|
||||||
|
|
||||||
context := get_2dcontext(canv) or { panic('wow') }
|
context := get_2dcontext(canv) or { panic('wow') }
|
||||||
mut drawing := false
|
mut state := DrawState{}
|
||||||
mut x := int(0)
|
canv.add_event_listener('mousedown', fn [mut state] (_ jsdom.IEventTarget, event jsdom.IEvent) {
|
||||||
mut y := int(0)
|
state.drawing = true
|
||||||
canv.add_event_listener('mousedown', fn [mut drawing, mut x, mut y] (_ jsdom.IEventTarget, event jsdom.IEvent) {
|
|
||||||
drawing = true
|
|
||||||
if event is jsdom.MouseEvent {
|
if event is jsdom.MouseEvent {
|
||||||
x = event.offset_x()
|
state.x = event.offset_x()
|
||||||
y = event.offset_y()
|
state.y = event.offset_y()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
canv.add_event_listener('mousemove', fn [context, drawing, mut x, mut y] (_ jsdom.IEventTarget, event jsdom.IEvent) {
|
canv.add_event_listener('mousemove', fn [context, mut state] (_ jsdom.IEventTarget, event jsdom.IEvent) {
|
||||||
if drawing {
|
if state.drawing {
|
||||||
if event is jsdom.MouseEvent {
|
if event is jsdom.MouseEvent {
|
||||||
draw_line(context, x, y, event.offset_x(), event.offset_y())
|
draw_line(context, state.x, state.y, event.offset_x(), event.offset_y())
|
||||||
x = event.offset_x()
|
state.x = event.offset_x()
|
||||||
y = event.offset_y()
|
state.y = event.offset_y()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
jsdom.window.add_event_listener('mouseup', fn [context, mut drawing, mut x, mut y] (_ jsdom.IEventTarget, event jsdom.IEvent) {
|
jsdom.window.add_event_listener('mouseup', fn [context, mut state] (_ jsdom.IEventTarget, event jsdom.IEvent) {
|
||||||
if drawing {
|
if state.drawing {
|
||||||
if event is jsdom.MouseEvent {
|
if event is jsdom.MouseEvent {
|
||||||
draw_line(context, x, y, event.offset_x(), event.offset_y())
|
draw_line(context, state.x, state.y, event.offset_x(), event.offset_y())
|
||||||
}
|
}
|
||||||
x = 0
|
state.x = 0
|
||||||
y = 0
|
state.y = 0
|
||||||
drawing = false
|
state.drawing = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
elem.add_event_listener('click', fn [context, canv] (_ jsdom.IEventTarget, _ jsdom.IEvent) {
|
elem.add_event_listener('click', fn [context, canv] (_ jsdom.IEventTarget, _ jsdom.IEvent) {
|
||||||
context.clear_rect(0, 0, canv.width(), canv.height())
|
context.clear_rect(0, 0, canv.width(), canv.height())
|
||||||
})
|
})
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ fn (mut g JsGen) get_str_fn(typ ast.Type) string {
|
||||||
unwrapped = ast.u64_type
|
unwrapped = ast.u64_type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if typ.has_flag(.optional) {
|
if typ.has_flag(.optional) {
|
||||||
unwrapped.set_flag(.optional)
|
unwrapped.set_flag(.optional)
|
||||||
}
|
}
|
||||||
|
@ -50,6 +51,9 @@ fn (mut g JsGen) final_gen_str(typ StrType) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
styp := typ.styp
|
styp := typ.styp
|
||||||
|
if styp == 'any' {
|
||||||
|
return
|
||||||
|
}
|
||||||
str_fn_name := styp_to_str_fn_name(styp)
|
str_fn_name := styp_to_str_fn_name(styp)
|
||||||
if typ.typ.has_flag(.optional) {
|
if typ.typ.has_flag(.optional) {
|
||||||
g.gen_str_for_option(typ.typ, styp, str_fn_name)
|
g.gen_str_for_option(typ.typ, styp, str_fn_name)
|
||||||
|
@ -346,37 +350,25 @@ fn (mut g JsGen) gen_str_for_interface(info ast.Interface, styp string, str_fn_n
|
||||||
for typ in info.types {
|
for typ in info.types {
|
||||||
subtype := g.table.get_type_symbol(typ)
|
subtype := g.table.get_type_symbol(typ)
|
||||||
mut func_name := g.get_str_fn(typ)
|
mut func_name := g.get_str_fn(typ)
|
||||||
sym_has_str_method, _, _ := subtype.str_method_info()
|
sym_has_str_method, str_method_expects_ptr, _ := subtype.str_method_info()
|
||||||
if should_use_indent_func(subtype.kind) && !sym_has_str_method {
|
if should_use_indent_func(subtype.kind) && !sym_has_str_method {
|
||||||
func_name = 'indent_$func_name'
|
func_name = 'indent_$func_name'
|
||||||
}
|
}
|
||||||
|
deref := if sym_has_str_method && str_method_expects_ptr { ' ' } else { '.valueOf()' }
|
||||||
// str_intp
|
// str_intp
|
||||||
|
|
||||||
if typ == ast.string_type {
|
if typ == ast.string_type {
|
||||||
/*
|
fn_builder.write_string('\tif (x.val instanceof string)')
|
||||||
mut val := '${func_name}(${deref}($subtype.cname*)x._$subtype.cname'
|
fn_builder.write_string(' return "new string(${clean_interface_v_type_name}(" + x.val.str + ")");')
|
||||||
if should_use_indent_func(subtype.kind) && !sym_has_str_method {
|
|
||||||
val += ', indent_count'
|
|
||||||
}
|
|
||||||
val += ')'
|
|
||||||
val = val
|
|
||||||
*/
|
|
||||||
res := '"TODO"'
|
|
||||||
fn_builder.write_string('\tif (x._typ == _${styp}_${subtype.cname}_index)')
|
|
||||||
fn_builder.write_string(' return $res;')
|
|
||||||
} else {
|
} else {
|
||||||
/*
|
mut val := '${func_name}(x $deref'
|
||||||
mut val := '${func_name}(${deref}($subtype.cname*)x._$subtype.cname'
|
|
||||||
if should_use_indent_func(subtype.kind) && !sym_has_str_method {
|
if should_use_indent_func(subtype.kind) && !sym_has_str_method {
|
||||||
val += ', indent_count'
|
val += ', indent_count'
|
||||||
}
|
}
|
||||||
val += ')'
|
val += ')'
|
||||||
val = val
|
|
||||||
*/
|
fn_builder.write_string('\tif (x.val instanceof $subtype.cname)')
|
||||||
res := '"TODO'
|
fn_builder.write_string(' return new string("${clean_interface_v_type_name}(" + ${val}.str + ")");\n')
|
||||||
fn_builder.write_string('\tif (x._typ == _${styp}_${subtype.cname}_index)')
|
|
||||||
fn_builder.write_string(' return $res;\n')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn_builder.writeln('\treturn new string("unknown interface value");')
|
fn_builder.writeln('\treturn new string("unknown interface value");')
|
||||||
|
|
|
@ -46,7 +46,7 @@ fn (mut g JsGen) to_js_typ_val(t ast.Type) string {
|
||||||
styp = 'new ${g.js_name(sym.name)}(${g.to_js_typ_def_val(sym.name)})'
|
styp = 'new ${g.js_name(sym.name)}(${g.to_js_typ_def_val(sym.name)})'
|
||||||
}
|
}
|
||||||
.voidptr {
|
.voidptr {
|
||||||
styp = 'null'
|
styp = 'new voidptr(null)'
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -108,7 +108,7 @@ fn (mut g JsGen) sym_to_js_typ(sym ast.TypeSymbol) string {
|
||||||
styp = 'array'
|
styp = 'array'
|
||||||
}
|
}
|
||||||
.voidptr {
|
.voidptr {
|
||||||
styp = 'any'
|
styp = 'voidptr'
|
||||||
}
|
}
|
||||||
.rune {
|
.rune {
|
||||||
styp = 'rune'
|
styp = 'rune'
|
||||||
|
@ -137,7 +137,7 @@ fn (mut g JsGen) base_type(_t ast.Type) string {
|
||||||
pub fn (mut g JsGen) typ(t ast.Type) string {
|
pub fn (mut g JsGen) typ(t ast.Type) string {
|
||||||
sym := g.table.get_final_type_symbol(t)
|
sym := g.table.get_final_type_symbol(t)
|
||||||
if sym.kind == .voidptr {
|
if sym.kind == .voidptr {
|
||||||
return 'any'
|
return 'voidptr'
|
||||||
}
|
}
|
||||||
|
|
||||||
styp := g.base_type(t)
|
styp := g.base_type(t)
|
||||||
|
@ -157,7 +157,7 @@ pub fn (mut g JsGen) doc_typ(t ast.Type) string {
|
||||||
styp = 'void'
|
styp = 'void'
|
||||||
}
|
}
|
||||||
.voidptr {
|
.voidptr {
|
||||||
styp = 'any'
|
styp = 'voidptr'
|
||||||
}
|
}
|
||||||
.byteptr, .charptr {
|
.byteptr, .charptr {
|
||||||
styp = '${g.sym_to_js_typ(sym)}'
|
styp = '${g.sym_to_js_typ(sym)}'
|
||||||
|
@ -438,6 +438,18 @@ fn (mut g JsGen) gen_builtin_type_defs() {
|
||||||
to_jsval: 'this.arr'
|
to_jsval: 'this.arr'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
'voidptr' {
|
||||||
|
g.gen_builtin_prototype(
|
||||||
|
typ_name: typ_name
|
||||||
|
val_name: 'val'
|
||||||
|
default_value: 'null'
|
||||||
|
constructor: 'this.val = val;'
|
||||||
|
value_of: 'this'
|
||||||
|
to_string: '"voidptr(" + this.val + ")"'
|
||||||
|
eq: 'this.val === other.val'
|
||||||
|
to_jsval: 'this.val'
|
||||||
|
)
|
||||||
|
}
|
||||||
'any' {
|
'any' {
|
||||||
g.gen_builtin_prototype(
|
g.gen_builtin_prototype(
|
||||||
typ_name: typ_name
|
typ_name: typ_name
|
||||||
|
|
|
@ -155,15 +155,32 @@ fn (mut g JsGen) gen_copy_for_struct(info ast.Struct, styp string, copy_fn_name
|
||||||
g.definitions.writeln(fn_builder.str())
|
g.definitions.writeln(fn_builder.str())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn_builder.writeln('function ${copy_fn_name}(it) {')
|
fn_builder.writeln('function ${copy_fn_name}(it) { return it }')
|
||||||
|
|
||||||
|
/*
|
||||||
tmp := g.new_tmp_var()
|
tmp := g.new_tmp_var()
|
||||||
fn_builder.writeln('\tlet $tmp = new ${styp}({});')
|
fn_builder.writeln('\tlet $tmp = new ${styp}({});')
|
||||||
for field in info.fields {
|
for field in info.fields {
|
||||||
|
println(field)
|
||||||
|
if field.name.len == 0 {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
mut shall_copy := true
|
||||||
|
for attr in field.attrs {
|
||||||
|
if attr.name == 'noinit' {
|
||||||
|
shall_copy = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if shall_copy {
|
||||||
func_name := g.get_copy_fn(field.typ)
|
func_name := g.get_copy_fn(field.typ)
|
||||||
fn_builder.writeln('\t${tmp}.$field.name = ${func_name}(it.$field.name);')
|
fn_builder.writeln('\t${tmp}.$field.name = ${func_name}(it.$field.name);')
|
||||||
|
} else {
|
||||||
|
fn_builder.writeln('\t${tmp}.$field.name = it.$field.name')
|
||||||
}
|
}
|
||||||
fn_builder.writeln('\treturn $tmp;\n}')
|
}
|
||||||
|
}
|
||||||
|
fn_builder.writeln('\treturn $tmp;\n}')*/
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g JsGen) final_gen_copy(typ StrType) {
|
fn (mut g JsGen) final_gen_copy(typ StrType) {
|
||||||
|
@ -181,9 +198,9 @@ fn (mut g JsGen) final_gen_copy(typ StrType) {
|
||||||
g.gen_copy_for_option(typ.typ, styp, copy_fn_name)
|
g.gen_copy_for_option(typ.typ, styp, copy_fn_name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
match sym.kind {
|
match styp {
|
||||||
.byte, .u8, .u16, .u32, .u64, .i16, .int, .i64, .isize, .usize, .bool, .int_literal,
|
'byte', 'u8', 'u16', 'u32', 'u64', 'i16', 'int', 'i64', 'isize', 'usize', 'bool',
|
||||||
.float_literal, .f32, .f64 {
|
'int_literal', 'float_literal', 'f32', 'f64', 'voidptr' {
|
||||||
g.definitions.writeln('function ${sym.cname}_\$copy(it) { return new ${sym.cname}(it.val); }')
|
g.definitions.writeln('function ${sym.cname}_\$copy(it) { return new ${sym.cname}(it.val); }')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ const (
|
||||||
'Array', 'Map', 'document']
|
'Array', 'Map', 'document']
|
||||||
// used to generate type structs
|
// used to generate type structs
|
||||||
v_types = ['i8', 'i16', 'int', 'i64', 'byte', 'u16', 'u32', 'u64', 'f32', 'f64',
|
v_types = ['i8', 'i16', 'int', 'i64', 'byte', 'u16', 'u32', 'u64', 'f32', 'f64',
|
||||||
'int_literal', 'float_literal', 'bool', 'string', 'map', 'array', 'rune', 'any']
|
'int_literal', 'float_literal', 'bool', 'string', 'map', 'array', 'rune', 'any', 'voidptr']
|
||||||
shallow_equatables = [ast.Kind.i8, .i16, .int, .i64, .byte, .u16, .u32, .u64, .f32, .f64,
|
shallow_equatables = [ast.Kind.i8, .i16, .int, .i64, .byte, .u16, .u32, .u64, .f32, .f64,
|
||||||
.int_literal, .float_literal, .bool, .string]
|
.int_literal, .float_literal, .bool, .string]
|
||||||
)
|
)
|
||||||
|
@ -1709,7 +1709,7 @@ fn (mut g JsGen) gen_interface_decl(it ast.InterfaceDecl) {
|
||||||
// TODO: interfaces are always `pub`?
|
// TODO: interfaces are always `pub`?
|
||||||
name := g.js_name(it.name)
|
name := g.js_name(it.name)
|
||||||
g.push_pub_var('/** @type $name */\n\t\t$name')
|
g.push_pub_var('/** @type $name */\n\t\t$name')
|
||||||
g.writeln('function ${g.js_name(it.name)} (arg) { return arg; }')
|
g.writeln('function ${g.js_name(it.name)} (arg) { return new \$ref(arg); }')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g JsGen) gen_optional_error(expr ast.Expr) {
|
fn (mut g JsGen) gen_optional_error(expr ast.Expr) {
|
||||||
|
@ -2335,6 +2335,7 @@ fn (mut g JsGen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var M
|
||||||
g.write(' instanceof ')
|
g.write(' instanceof ')
|
||||||
g.expr(branch.exprs[sumtype_index])
|
g.expr(branch.exprs[sumtype_index])
|
||||||
} else if sym.kind == .interface_ {
|
} else if sym.kind == .interface_ {
|
||||||
|
g.write('.val')
|
||||||
if branch.exprs[sumtype_index] is ast.TypeNode {
|
if branch.exprs[sumtype_index] is ast.TypeNode {
|
||||||
g.write(' instanceof ')
|
g.write(' instanceof ')
|
||||||
g.expr(branch.exprs[sumtype_index])
|
g.expr(branch.exprs[sumtype_index])
|
||||||
|
|
Loading…
Reference in New Issue