js,jsdom: Canvas & context API; Added TypeSymbol.is_js_compatible & temporary hacks for JS ifaces (#12526)
parent
258d0d6df7
commit
243e66a106
|
@ -1,82 +1,90 @@
|
|||
/*
|
||||
import jsdom
|
||||
|
||||
fn get_2dcontext(canvas jsdom.IElement) ?jsdom.CanvasRenderingContext2D {
|
||||
if canvas is jsdom.HTMLCanvasElement {
|
||||
c := canvas.get_context('2d')
|
||||
match c {
|
||||
jsdom.CanvasRenderingContext2D {
|
||||
return c
|
||||
fn get_canvas(elem JS.HTMLElement) &JS.HTMLCanvasElement {
|
||||
match elem {
|
||||
JS.HTMLCanvasElement {
|
||||
return elem
|
||||
}
|
||||
else {
|
||||
return error('cannot fetch 2d context')
|
||||
panic('Not a canvas')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return error('canvas is not an HTMLCanvasElement')
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_line(context jsdom.CanvasRenderingContext2D, x1 int, y1 int, x2 int, y2 int) {
|
||||
context.begin_path()
|
||||
context.set_stroke_style('black')
|
||||
context.set_line_width(1)
|
||||
context.move_to(x1, y1)
|
||||
context.line_to(x2, y2)
|
||||
fn draw_line(mut context JS.CanvasRenderingContext2D, x1 int, y1 int, x2 int, y2 int) {
|
||||
context.beginPath()
|
||||
context.strokeStyle = 'black'.str
|
||||
context.lineWidth = JS.Number(1)
|
||||
context.moveTo(x1, y1)
|
||||
context.lineTo(x2, y2)
|
||||
context.stroke()
|
||||
context.close_path()
|
||||
context.closePath()
|
||||
}
|
||||
|
||||
struct DrawState {
|
||||
mut:
|
||||
context JS.CanvasRenderingContext2D
|
||||
drawing bool
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
fn main() {
|
||||
window := jsdom.window()
|
||||
document := jsdom.document
|
||||
clear_btn := document.getElementById('clearButton'.str) ?
|
||||
canvas_elem := document.getElementById('canvas'.str) ?
|
||||
canvas := get_canvas(canvas_elem)
|
||||
ctx := canvas.getContext('2d'.str, js_undefined()) ?
|
||||
context := match ctx {
|
||||
JS.CanvasRenderingContext2D {
|
||||
ctx
|
||||
}
|
||||
else {
|
||||
panic('can not get 2d context')
|
||||
}
|
||||
}
|
||||
mut state := DrawState{context, false, 0, 0}
|
||||
|
||||
elem := document.get_element_by_id('myButton') ?
|
||||
elemc := document.get_element_by_id('myCanvas') or { panic('no canvas') }
|
||||
canv := jsdom.get_html_canvas_element(elemc) or { panic('expected canvas') }
|
||||
|
||||
context := canv.get_context_2d()
|
||||
mut state := DrawState{}
|
||||
canv.add_event_listener('mousedown', fn [mut state] (_ jsdom.IEventTarget, event jsdom.IEvent) {
|
||||
canvas.addEventListener('mousedown'.str, fn [mut state] (event JS.Event) {
|
||||
state.drawing = true
|
||||
if event is jsdom.MouseEvent {
|
||||
state.x = event.offset_x()
|
||||
state.y = event.offset_y()
|
||||
match event {
|
||||
JS.MouseEvent {
|
||||
state.x = int(event.offsetX)
|
||||
state.y = int(event.offsetY)
|
||||
}
|
||||
})
|
||||
|
||||
canv.add_event_listener('mousemove', fn [context, mut state] (_ jsdom.IEventTarget, event jsdom.IEvent) {
|
||||
else {}
|
||||
}
|
||||
}, JS.EventListenerOptions{})
|
||||
canvas.addEventListener('mousemove'.str, fn [mut state] (event JS.Event) {
|
||||
if state.drawing {
|
||||
if event is jsdom.MouseEvent {
|
||||
draw_line(context, state.x, state.y, event.offset_x(), event.offset_y())
|
||||
state.x = event.offset_x()
|
||||
state.y = event.offset_y()
|
||||
match event {
|
||||
JS.MouseEvent {
|
||||
draw_line(mut state.context, state.x, state.y, int(event.offsetX),
|
||||
int(event.offsetY))
|
||||
state.x = int(event.offsetX)
|
||||
state.y = int(event.offsetY)
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
})
|
||||
}, JS.EventListenerOptions{})
|
||||
|
||||
jsdom.window.add_event_listener('mouseup', fn [context, mut state] (_ jsdom.IEventTarget, event jsdom.IEvent) {
|
||||
window.addEventListener('mouseup'.str, fn [mut state] (event JS.Event) {
|
||||
if state.drawing {
|
||||
if event is jsdom.MouseEvent {
|
||||
draw_line(context, state.x, state.y, event.offset_x(), event.offset_y())
|
||||
match event {
|
||||
JS.MouseEvent {
|
||||
draw_line(mut state.context, state.x, state.y, int(event.offsetX),
|
||||
int(event.offsetY))
|
||||
}
|
||||
else {}
|
||||
}
|
||||
state.x = 0
|
||||
state.y = 0
|
||||
state.drawing = false
|
||||
}
|
||||
})
|
||||
elem.add_event_listener('click', fn [context, canv] (_ jsdom.IEventTarget, _ jsdom.IEvent) {
|
||||
context.clear_rect(0, 0, canv.width(), canv.height())
|
||||
})
|
||||
}
|
||||
*/
|
||||
|
||||
fn main() {
|
||||
panic('jsdom is being refactored; This example will be available soon')
|
||||
}, JS.EventListenerOptions{})
|
||||
clear_btn.addEventListener('click'.str, fn [mut state, canvas] (_ JS.Event) {
|
||||
state.context.clearRect(0, 0, canvas.width, canvas.height)
|
||||
}, JS.EventListenerOptions{})
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<body class="main">
|
||||
<title>Drawing with mouse events</title>
|
||||
<input type="button" id="myButton" value="Clear canvas">
|
||||
<canvas style="border: 1px solid black;" width="720" height="480" id="myCanvas"></canvas>
|
||||
<input type="button" id="clearButton" value="Clear canvas">
|
||||
<canvas style="border: 1px solid black;" width="720" height="480" id="canvas"></canvas>
|
||||
<script type="text/javascript" src="draw.js"></script>
|
||||
|
||||
</body>
|
|
@ -57,6 +57,34 @@ pub interface JS.Map {
|
|||
|
||||
pub interface JS.Any {}
|
||||
|
||||
pub fn js_is_null(x JS.Any) bool {
|
||||
res := false
|
||||
#res.val = x === null
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn js_is_undefined(x JS.Any) bool {
|
||||
res := false
|
||||
#res.val = x === undefined
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn js_null() JS.Any {
|
||||
mut obj := JS.Any{}
|
||||
#obj = null;
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
pub fn js_undefined() JS.Any {
|
||||
mut obj := JS.Any{}
|
||||
#obj = undefined;
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
pub interface JS.Array {
|
||||
JS.Any // map(fn (JS.Any) JS.Any) JS.Array
|
||||
map(JS.Any) JS.Array
|
||||
|
|
|
@ -8,6 +8,13 @@ pub mut:
|
|||
will_read_frequently bool
|
||||
}
|
||||
|
||||
pub fn (settings CanvasRenderingContext2DSettings) to_js() JS.Any {
|
||||
mut object := JS.Any{}
|
||||
#object = { alpha: settings.alpha, colorSpace: settings.color_space.str, desynchronized: settings.desynchronized.val, willReadFrequently: settings.will_read_frequently.val };
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
pub interface JS.DOMMatrix2DInit {
|
||||
mut:
|
||||
a JS.Number
|
||||
|
@ -168,9 +175,9 @@ pub struct JS.EventListenerOptions {
|
|||
}
|
||||
|
||||
pub interface JS.EventTarget {
|
||||
addEventListener(cb EventCallback, options JS.EventListenerOptions)
|
||||
addEventListener(event JS.String, cb EventCallback, options JS.EventListenerOptions)
|
||||
dispatchEvent(event JS.Event) JS.Boolean
|
||||
removeEventListener(cb EventCallback, options JS.EventListenerOptions)
|
||||
removeEventListener(event JS.String, cb EventCallback, options JS.EventListenerOptions)
|
||||
}
|
||||
|
||||
// Event is an event which takes place in the DOM.
|
||||
|
@ -320,6 +327,7 @@ pub interface JS.Document {
|
|||
lastModified JS.String
|
||||
inputEncoding JS.String
|
||||
implementation JS.DOMImplementation
|
||||
getElementById(id JS.String) ?JS.HTMLElement
|
||||
mut:
|
||||
bgColor JS.String
|
||||
body JS.HTMLElement
|
||||
|
@ -368,6 +376,14 @@ pub interface JS.Element {
|
|||
scroll(x JS.Number, y JS.Number)
|
||||
scrollBy(x JS.Number, y JS.Number)
|
||||
toggleAttribute(qualifiedName JS.String, force JS.Boolean) JS.Boolean
|
||||
getElementsByClassName(className JS.String) JS.HTMLCollection
|
||||
getElementsByTagName(qualifiedName JS.String) JS.HTMLCollection
|
||||
getEelementsByTagNameNS(namespaecURI JS.String, localName JS.String) JS.HTMLCollection
|
||||
hasAttribute(qualifiedName JS.String) JS.Boolean
|
||||
hasAttributeNS(namespace JS.String, localName JS.String) JS.Boolean
|
||||
hasAttributes() JS.Boolean
|
||||
hasPointerCapture(pointerId JS.Number) JS.Boolean
|
||||
matches(selectors JS.String) JS.Boolean
|
||||
mut:
|
||||
className JS.String
|
||||
id JS.String
|
||||
|
@ -383,6 +399,13 @@ pub const (
|
|||
document = JS.Document{}
|
||||
)
|
||||
|
||||
pub fn window() JS.Window {
|
||||
mut x := JS.Any(voidptr(0))
|
||||
#x = window;
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
fn init() {
|
||||
#jsdom__document = document;
|
||||
}
|
||||
|
@ -398,3 +421,143 @@ pub fn event_listener(callback fn (JS.EventTarget, JS.Event)) EventCallback {
|
|||
callback(target, event)
|
||||
}
|
||||
}
|
||||
|
||||
pub interface JS.HTMLCollection {
|
||||
length JS.Number
|
||||
item(idx JS.Number) ?JS.Any
|
||||
namedItem(name JS.String) ?JS.Any
|
||||
}
|
||||
|
||||
pub interface JS.HTMLElement {
|
||||
JS.Element
|
||||
accessKeyLabel JS.String
|
||||
offsetHeight JS.Number
|
||||
offsetLeft JS.Number
|
||||
offsetParent JS.Any
|
||||
offsetTop JS.Number
|
||||
offsetWidth JS.Number
|
||||
click()
|
||||
mut:
|
||||
accessKey JS.String
|
||||
autocapitalize JS.String
|
||||
dir JS.String
|
||||
draggable JS.Boolean
|
||||
hidden JS.Boolean
|
||||
innerText JS.String
|
||||
lang JS.String
|
||||
outerText JS.String
|
||||
spellcheck JS.Boolean
|
||||
title JS.String
|
||||
translate JS.Boolean
|
||||
}
|
||||
|
||||
pub fn JS.HTMLElement.prototype.constructor() JS.HTMLElement
|
||||
|
||||
pub interface JS.HTMLEmbedElement {
|
||||
getSVGDocument() ?JS.Document
|
||||
mut:
|
||||
align JS.String
|
||||
height JS.String
|
||||
src JS.String
|
||||
width JS.String
|
||||
}
|
||||
|
||||
pub fn html_embed_type(embed JS.HTMLEmbedElement) JS.String {
|
||||
mut str := JS.String{}
|
||||
#str = embed.type
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
pub fn JS.HTMLEmbedElement.prototype.constructor() JS.HTMLEmbedElement
|
||||
|
||||
pub type CanvasContext = JS.CanvasRenderingContext2D
|
||||
| JS.WebGL2RenderingContext
|
||||
| JS.WebGLRenderingContext
|
||||
|
||||
pub interface JS.HTMLCanvasElement {
|
||||
JS.HTMLElement
|
||||
getContext(contextId JS.String, options JS.Any) ?CanvasContext
|
||||
mut:
|
||||
height JS.Number
|
||||
width JS.Number
|
||||
}
|
||||
|
||||
pub type FillStyle = JS.CanvasGradient | JS.CanvasPattern | JS.String
|
||||
|
||||
pub interface JS.CanvasRenderingContext2D {
|
||||
canvas JS.HTMLCanvasElement
|
||||
beginPath()
|
||||
clip(path JS.Path2D, fillRule JS.String)
|
||||
fill(path JS.Path2D, fillRule JS.String)
|
||||
isPointInPath(path JS.Path2D, x JS.Number, y JS.Number, fillRule JS.String) JS.Boolean
|
||||
isPointInStroke(path JS.Path2D, x JS.Number, y JS.Number) JS.Boolean
|
||||
stoke(path JS.Path2D)
|
||||
createLinearGradient(x0 JS.Number, y0 JS.Number, x1 JS.Number, y1 JS.Number) JS.CanvasGradient
|
||||
createRadialGradient(x0 JS.Number, y0 JS.Number, r0 JS.Number, x1 JS.Number, y1 JS.Number, r1 JS.Number) JS.CanvasGradient
|
||||
createPattern(image JS.CanvasImageSource, repetition JS.String) ?JS.CanvasPattern
|
||||
arc(x JS.Number, y JS.Number, radius JS.Number, startAngle JS.Number, endAngle JS.Number, counterclockwise JS.Boolean)
|
||||
arcTo(x1 JS.Number, y1 JS.Number, x2 JS.Number, y2 JS.Number, radius JS.Number)
|
||||
bezierCurveTo(cp1x JS.Number, cp1y JS.Number, cp2x JS.Number, cp2y JS.Number, x JS.Number, y JS.Number)
|
||||
closePath()
|
||||
ellipse(x JS.Number, y JS.Number, radiusX JS.Number, radiusY JS.Number, rotation JS.Number, startAngle JS.Number, endAngle JS.Number, counterclockwise JS.Boolean)
|
||||
lineTo(x JS.Number, y JS.Number)
|
||||
moveTo(x JS.Number, y JS.Number)
|
||||
quadraticCurveTo(cpx JS.Number, cpy JS.Number, x JS.Number, y JS.Number)
|
||||
rect(x JS.Number, y JS.Number, w JS.Number, h JS.Number)
|
||||
getLineDash() JS.Array
|
||||
setLineDash(segments JS.Array)
|
||||
clearRect(x JS.Number, y JS.Number, w JS.Number, h JS.Number)
|
||||
fillRect(x JS.Number, y JS.Number, w JS.null, h JS.Number)
|
||||
strokeRect(x JS.Number, y JS.Number, w JS.Number, h JS.Number)
|
||||
getTransformt() JS.DOMMatrix
|
||||
resetTransform()
|
||||
rotate(angle JS.Number)
|
||||
scale(x JS.Number, y JS.Number)
|
||||
setTransform(matrix JS.DOMMatrix)
|
||||
transform(a JS.Number, b JS.Number, c JS.Number, d JS.Number, e JS.Number, f JS.Number)
|
||||
translate(x JS.Number, y JS.Number)
|
||||
drawFocusIfNeeded(path JS.Path2D, element JS.Element)
|
||||
stroke()
|
||||
mut:
|
||||
lineCap JS.String
|
||||
lineDashOffset JS.Number
|
||||
lineJoin JS.String
|
||||
lineWidth JS.Number
|
||||
miterLimit JS.Number
|
||||
fillStyle FillStyle
|
||||
strokeStyle FillStyle
|
||||
globalAlpha JS.Number
|
||||
globalCompositeOperation JS.String
|
||||
}
|
||||
|
||||
pub interface JS.CanvasGradient {
|
||||
addColorStop(offset JS.Number, color JS.String)
|
||||
}
|
||||
|
||||
pub interface JS.CanvasPattern {
|
||||
setTransform(transform JS.DOMMatrix)
|
||||
}
|
||||
|
||||
pub interface JS.WebGLRenderingContext {
|
||||
canvas JS.HTMLCanvasElement
|
||||
drawingBufferHeight JS.Number
|
||||
drawingBufferWidth JS.Number
|
||||
}
|
||||
|
||||
pub interface JS.WebGL2RenderingContext {
|
||||
JS.WebGLRenderingContext
|
||||
}
|
||||
|
||||
pub interface JS.Window {
|
||||
JS.EventTarget
|
||||
closed JS.Boolean
|
||||
devicePixelRatio JS.Number
|
||||
document JS.Document
|
||||
frameElement JS.Element
|
||||
innerHeight JS.Number
|
||||
innerWidth JS.Number
|
||||
length JS.Number
|
||||
}
|
||||
|
||||
pub interface JS.Path2D {}
|
||||
|
|
|
@ -267,7 +267,12 @@ pub fn (t &Table) is_same_method(f &Fn, func &Fn) string {
|
|||
for i in 0 .. f.params.len {
|
||||
// don't check receiver for `.typ`
|
||||
has_unexpected_type := i > 0 && f.params[i].typ != func.params[i].typ
|
||||
|
||||
// temporary hack for JS ifaces
|
||||
lsym := t.get_type_symbol(f.params[i].typ)
|
||||
rsym := t.get_type_symbol(func.params[i].typ)
|
||||
if lsym.language == .js && rsym.language == .js {
|
||||
return ''
|
||||
}
|
||||
has_unexpected_mutability := !f.params[i].is_mut && func.params[i].is_mut
|
||||
|
||||
if has_unexpected_type || has_unexpected_mutability {
|
||||
|
|
|
@ -1247,6 +1247,34 @@ pub fn (t &TypeSymbol) find_method_with_generic_parent(name string) ?Fn {
|
|||
return none
|
||||
}
|
||||
|
||||
// is_js_compatible returns true if type can be converted to JS type and from JS type back to V type
|
||||
pub fn (t &TypeSymbol) is_js_compatible() bool {
|
||||
mut table := global_table
|
||||
if t.kind == .void {
|
||||
return true
|
||||
}
|
||||
if t.kind == .function {
|
||||
return true
|
||||
}
|
||||
if t.language == .js || t.name.starts_with('JS.') {
|
||||
return true
|
||||
}
|
||||
match t.info {
|
||||
SumType {
|
||||
for variant in t.info.variants {
|
||||
sym := table.get_final_type_symbol(variant)
|
||||
if !sym.is_js_compatible() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (t &TypeSymbol) str_method_info() (bool, bool, int) {
|
||||
mut has_str_method := false
|
||||
mut expects_ptr := false
|
||||
|
|
|
@ -413,8 +413,10 @@ pub fn (mut c Checker) sum_type_decl(node ast.SumTypeDecl) {
|
|||
variant.pos)
|
||||
} else if sym.kind in [.placeholder, .int_literal, .float_literal] {
|
||||
c.error('unknown type `$sym.name`', variant.pos)
|
||||
} else if sym.kind == .interface_ {
|
||||
} else if sym.kind == .interface_ && sym.language != .js {
|
||||
c.error('sum type cannot hold an interface', variant.pos)
|
||||
} else if sym.kind == .struct_ && sym.language == .js {
|
||||
c.error('sum type cannot hold an JS struct', variant.pos)
|
||||
}
|
||||
if sym.name.trim_prefix(sym.mod + '.') == node.name {
|
||||
c.error('sum type cannot hold itself', variant.pos)
|
||||
|
@ -555,8 +557,7 @@ pub fn (mut c Checker) interface_decl(mut node ast.InterfaceDecl) {
|
|||
c.ensure_type_exists(method.return_type, method.return_type_pos) or { return }
|
||||
if is_js {
|
||||
mtyp := c.table.get_type_symbol(method.return_type)
|
||||
if (mtyp.language != .js && !method.return_type.is_void())
|
||||
&& !mtyp.name.starts_with('JS.') {
|
||||
if !mtyp.is_js_compatible() {
|
||||
c.error('method $method.name returns non JS type', method.pos)
|
||||
}
|
||||
}
|
||||
|
@ -567,8 +568,7 @@ pub fn (mut c Checker) interface_decl(mut node ast.InterfaceDecl) {
|
|||
c.ensure_type_exists(param.typ, param.pos) or { return }
|
||||
if is_js {
|
||||
ptyp := c.table.get_type_symbol(param.typ)
|
||||
if (ptyp.kind != .function && ptyp.language != .js
|
||||
&& !ptyp.name.starts_with('JS.')) && !(j == method.params.len - 1
|
||||
if !ptyp.is_js_compatible() && !(j == method.params.len - 1
|
||||
&& method.is_variadic) {
|
||||
c.error('method `$method.name` accepts non JS type as parameter',
|
||||
method.pos)
|
||||
|
@ -595,7 +595,7 @@ pub fn (mut c Checker) interface_decl(mut node ast.InterfaceDecl) {
|
|||
c.ensure_type_exists(field.typ, field.pos) or { return }
|
||||
if is_js {
|
||||
tsym := c.table.get_type_symbol(field.typ)
|
||||
if tsym.language != .js && !tsym.name.starts_with('JS.') && tsym.kind != .function {
|
||||
if !tsym.is_js_compatible() {
|
||||
c.error('field `$field.name` uses non JS type', field.pos)
|
||||
}
|
||||
}
|
||||
|
@ -5313,6 +5313,7 @@ pub fn (mut c Checker) expr(node ast.Expr) ast.Type {
|
|||
defer {
|
||||
c.expr_level--
|
||||
}
|
||||
|
||||
// c.expr_level set to 150 so that stack overflow does not occur on windows
|
||||
if c.expr_level > 150 {
|
||||
c.error('checker: too many expr levels: $c.expr_level ', node.position())
|
||||
|
@ -6407,6 +6408,7 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym ast.TypeSym
|
|||
} else {
|
||||
expr_type = expr_types[0].typ
|
||||
}
|
||||
|
||||
c.smartcast(node.cond, node.cond_type, expr_type, mut branch.scope)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -620,11 +620,14 @@ fn (mut g JsGen) gen_method_decl(it ast.FnDecl, typ FnGenType) {
|
|||
if is_varg {
|
||||
g.writeln('$arg_name = new array(new array_buffer({arr: $arg_name,len: new int(${arg_name}.length),index_start: new int(0)}));')
|
||||
} else {
|
||||
asym := g.table.get_type_symbol(arg.typ)
|
||||
if asym.kind != .interface_ && asym.language != .js {
|
||||
if arg.typ.is_ptr() || arg.is_mut {
|
||||
g.writeln('$arg_name = new \$ref($arg_name)')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
g.stmts(it.stmts)
|
||||
g.writeln('}')
|
||||
|
||||
|
@ -743,7 +746,9 @@ fn (mut g JsGen) gen_anon_fn(mut fun ast.AnonFn) {
|
|||
if is_varg {
|
||||
g.writeln('$arg_name = new array(new array_buffer({arr: $arg_name,len: new int(${arg_name}.length),index_start: new int(0)}));')
|
||||
} else {
|
||||
if arg.typ.is_ptr() || arg.is_mut {
|
||||
asym := g.table.get_type_symbol(arg.typ)
|
||||
|
||||
if arg.typ.is_ptr() || (arg.is_mut && asym.kind != .interface_ && asym.language != .js) {
|
||||
g.writeln('$arg_name = new \$ref($arg_name)')
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2343,20 +2343,53 @@ fn (mut g JsGen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var M
|
|||
} else {
|
||||
g.write('if (')
|
||||
}
|
||||
if sym.kind == .sum_type || sym.kind == .interface_ {
|
||||
x := branch.exprs[sumtype_index]
|
||||
|
||||
if x is ast.TypeNode {
|
||||
typ := g.unwrap_generic(x.typ)
|
||||
|
||||
tsym := g.table.get_type_symbol(typ)
|
||||
if tsym.language == .js && (tsym.name == 'JS.Number'
|
||||
|| tsym.name == 'JS.Boolean' || tsym.name == 'JS.String') {
|
||||
g.write('typeof ')
|
||||
}
|
||||
}
|
||||
}
|
||||
g.match_cond(cond_var)
|
||||
if sym.kind == .sum_type {
|
||||
x := branch.exprs[sumtype_index]
|
||||
if x is ast.TypeNode {
|
||||
typ := g.unwrap_generic(x.typ)
|
||||
tsym := g.table.get_type_symbol(typ)
|
||||
if tsym.language == .js && (tsym.name == 'JS.Number'
|
||||
|| tsym.name == 'JS.Boolean' || tsym.name == 'JS.String') {
|
||||
g.write(' === "${tsym.name[3..].to_lower()}"')
|
||||
} else {
|
||||
g.write(' instanceof ')
|
||||
g.expr(branch.exprs[sumtype_index])
|
||||
}
|
||||
} else {
|
||||
g.write(' instanceof ')
|
||||
g.expr(branch.exprs[sumtype_index])
|
||||
}
|
||||
} else if sym.kind == .interface_ {
|
||||
if !sym.name.starts_with('JS.') {
|
||||
g.write('.val')
|
||||
}
|
||||
if branch.exprs[sumtype_index] is ast.TypeNode {
|
||||
g.write(' instanceof ')
|
||||
g.expr(branch.exprs[sumtype_index])
|
||||
x := branch.exprs[sumtype_index]
|
||||
if x is ast.TypeNode {
|
||||
typ := g.unwrap_generic(x.typ)
|
||||
tsym := g.table.get_type_symbol(typ)
|
||||
if tsym.language == .js && (tsym.name == 'Number'
|
||||
|| tsym.name == 'Boolean' || tsym.name == 'String') {
|
||||
g.write(' === $tsym.name.to_lower()')
|
||||
} else {
|
||||
g.write(' instanceof ')
|
||||
g.expr(branch.exprs[sumtype_index])
|
||||
}
|
||||
} else {
|
||||
g.write(' instanceof ')
|
||||
|
||||
g.write('None__')
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue