parser: allow JS methods with more than 1 dot

pull/4905/head
spaceface777 2020-05-15 22:26:51 +02:00 committed by GitHub
parent 04744a5390
commit 7c9bb44784
5 changed files with 45 additions and 16 deletions

View File

@ -231,8 +231,8 @@ pub fn (g mut JsGen) new_tmp_var() string {
}
[inline]
fn js_name(name_ string) string {
name := name_.replace('.', '__')
fn js_name(name string) string {
// name := name_.replace('.', '__')
if name in js_reserved {
return 'v_$name'
}
@ -358,12 +358,13 @@ fn (g mut JsGen) expr(node ast.Expr) {
g.write("'$it.val'")
}
ast.CallExpr {
name := if it.name.starts_with('JS.') { it.name[3..] } else { it.name }
g.expr(it.left)
if it.is_method {
// example: foo.bar.baz()
g.write('.')
}
g.write('${js_name(it.name)}(')
g.write('${js_name(name)}(')
for i, arg in it.args {
g.expr(arg.expr)
if i != it.args.len - 1 {

View File

@ -1,5 +1,5 @@
// V_COMMIT_HASH d60233b
// V_CURRENT_COMMIT_HASH fc520d9
// V_COMMIT_HASH 04744a5
// V_CURRENT_COMMIT_HASH 04744a5
// Generated by the V compiler
"use strict";
@ -13,6 +13,8 @@ const CONSTANTS = Object.freeze({
/* namespace: main */
const main = (function () {
class Companies {
/**
* @param {{google: number, amazon: boolean, yahoo: string}} values - values for this class fields
@ -61,6 +63,7 @@ class Companies {
/* program entry point */
(async function() {
console.log("Hello from V.js!");
/** @type {string} - v */
const v = "done";
{
@ -76,6 +79,7 @@ class Companies {
const v_await = CONSTANTS.v_super + v_debugger;
/** @type {string} - v_finally */
let v_finally = "implemented";
console.log(v_await, v_finally);
/** @type {number} - dun */
const dun = CONSTANTS.i_am_a_const * 20;
for (let i = 0; i < 10; i++) {

View File

@ -1,3 +1,5 @@
fn JS.alert(arg string)
fn JS.console.log(arg string)
const (
i_am_a_const = 21214
@ -21,6 +23,8 @@ fn class(extends string, instanceof int) {
fn main() {
JS.console.log('Hello from V.js!')
v := "done"
{
_ := "block"
@ -33,6 +37,8 @@ fn main() {
await := super + debugger
mut finally := 'implemented'
JS.console.log(await, finally)
dun := i_am_a_const * 20
for i := 0; i < 10; i++ {}

View File

@ -10,16 +10,16 @@ import v.util
pub fn (mut p Parser) call_expr(is_c, is_js bool, mod string) ast.CallExpr {
first_pos := p.tok.position()
name := p.check_name()
fn_name := if is_c {
'C.$name'
'C.${p.check_name()}'
} else if is_js {
'JS.$name'
'JS.${p.check_js_name()}'
} else if mod.len > 0 {
'${mod}.$name'
'${mod}.${p.check_name()}'
} else {
name
p.check_name()
}
mut is_or_block_used := false
if fn_name == 'json.decode' {
p.expecting_type = true // Makes name_expr() parse the type (`User` in `json.decode(User, txt)`)`
@ -156,7 +156,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
mut name := ''
if p.tok.kind == .name {
// TODO high order fn
name = p.check_name()
name = if is_js { p.check_js_name() } else { p.check_name() }
if !is_js && !is_c && !p.pref.translated && util.contains_capital(name) {
p.error('function names cannot contain uppercase letters, use snake_case instead')
}

View File

@ -285,6 +285,22 @@ fn (mut p Parser) check(expected token.Kind) {
p.next()
}
// JS functions can have multiple dots in their name:
// JS.foo.bar.and.a.lot.more.dots()
fn (mut p Parser) check_js_name() string {
mut name := ''
for p.peek_tok.kind == .dot {
name += '${p.tok.lit}.'
p.next() // .name
p.next() // .dot
}
// last .name
name += p.tok.lit
p.next()
return name
}
fn (mut p Parser) check_name() string {
name := p.tok.lit
if p.peek_tok.kind == .dot && name in p.imports {
@ -754,8 +770,7 @@ pub fn (mut p Parser) name_expr() ast.Expr {
} else {
// fn call
// println('calling $p.tok.lit')
x := p.call_expr(is_c, is_js, mod) // TODO `node,typ :=` should work
node = x
node = p.call_expr(is_c, is_js, mod)
}
} else if p.peek_tok.kind == .lcbr && !p.inside_match && !p.inside_match_case && !p.inside_if &&
!p.inside_for {
@ -782,6 +797,9 @@ pub fn (mut p Parser) name_expr() ast.Expr {
} else if p.peek_tok.kind == .colon && p.prev_tok.kind != .str_dollar {
// `foo(key:val, key2:val2)`
return p.struct_init(true) // short_syntax:true
// JS. function call with more than 1 dot
} else if is_js && p.peek_tok.kind == .dot && p.peek_tok2.kind == .name {
node = p.call_expr(is_c, is_js, mod)
} else {
node = p.parse_ident(is_c, is_js)
}