345 lines
6.1 KiB
Plaintext
345 lines
6.1 KiB
Plaintext
/* comprehensive syntax test - exercises all AST paths */
|
|
|
|
// --- variables and constants ---
|
|
var a
|
|
var b = 1
|
|
var c = 2, d = 3
|
|
def PI = 3.14159
|
|
def MSG = "hello"
|
|
|
|
// --- number literals ---
|
|
var n_int = 42
|
|
var n_float = 3.14
|
|
var n_hex = 0xFF
|
|
var n_octal = 0o77
|
|
var n_binary = 0b1010
|
|
var n_underscore = 1_000_000
|
|
var n_exp = 1e10
|
|
var n_exp_neg = 2.5e-3
|
|
|
|
// --- string literals ---
|
|
var s_single = 'single'
|
|
var s_double = "double"
|
|
var s_escape = "tab\there\nnewline\\slash\"quote"
|
|
var s_unicode = "\u0041\u0042"
|
|
|
|
// --- template literals ---
|
|
var t_basic = `hello ${b} world`
|
|
var t_nested = `a ${b + c} b ${d}`
|
|
var t_expr = `result: ${b > 0 ? "yes" : "no"}`
|
|
|
|
// --- array literals ---
|
|
var arr_empty = []
|
|
var arr_simple = [1, 2, 3]
|
|
var arr_mixed = [1, "two", true, null]
|
|
var arr_nested = [[1, 2], [3, [4, 5]]]
|
|
|
|
// --- record/object literals ---
|
|
var rec_empty = {}
|
|
var rec_simple = {x: 1, y: 2}
|
|
var rec_nested = {a: {b: {c: 3}}}
|
|
var shorthand_var = 10
|
|
var rec_shorthand = {shorthand_var}
|
|
var rec_computed = {["key" + "1"]: 100}
|
|
var rec_method = {
|
|
greet() { return "hi" }
|
|
}
|
|
var rec_mixed = {
|
|
name: "test",
|
|
value: 42,
|
|
nested: {inner: true},
|
|
items: [1, 2, 3]
|
|
}
|
|
|
|
// --- all binary arithmetic operators ---
|
|
var arith_add = 1 + 2
|
|
var arith_sub = 5 - 3
|
|
var arith_mul = 4 * 5
|
|
var arith_div = 10 / 3
|
|
var arith_mod = 10 % 3
|
|
var arith_pow = 2 ** 8
|
|
|
|
// --- comparison operators ---
|
|
var cmp_lt = 1 < 2
|
|
var cmp_gt = 2 > 1
|
|
var cmp_lte = 1 <= 1
|
|
var cmp_gte = 2 >= 2
|
|
var cmp_eq = 1 == 1
|
|
var cmp_neq = 1 != 2
|
|
|
|
// --- logical operators ---
|
|
var log_and = true && false
|
|
var log_or = false || true
|
|
var log_not = !false
|
|
|
|
// --- bitwise operators ---
|
|
var bit_and = 0xFF & 0x0F
|
|
var bit_or = 0xF0 | 0x0F
|
|
var bit_xor = 0xFF ^ 0x0F
|
|
var bit_not = ~0
|
|
var bit_shl = 1 << 8
|
|
var bit_shr = 256 >> 4
|
|
var bit_shru = -1 >>> 0
|
|
|
|
// --- nullish coalescing ---
|
|
var nullish = null ?? "default"
|
|
|
|
// --- ternary operator ---
|
|
var tern = b > 0 ? "pos" : "neg"
|
|
var tern_nested = b > 0 ? (b > 10 ? "big" : "small") : "neg"
|
|
|
|
// --- comma operator ---
|
|
var comma_result = (1, 2, 3)
|
|
|
|
// --- unary operators ---
|
|
var unary_pos = +b
|
|
var unary_neg = -b
|
|
|
|
// --- increment/decrement ---
|
|
var inc_val = 0
|
|
inc_val++
|
|
inc_val--
|
|
;++inc_val
|
|
;--inc_val
|
|
|
|
// --- all compound assignments ---
|
|
var ca = 10
|
|
ca += 5
|
|
ca -= 3
|
|
ca *= 2
|
|
ca /= 4
|
|
ca %= 3
|
|
ca **= 2
|
|
ca <<= 1
|
|
ca >>= 1
|
|
ca >>>= 0
|
|
ca &= 0xFF
|
|
ca |= 0x01
|
|
ca ^= 0x10
|
|
ca &&= true
|
|
ca ||= false
|
|
ca ??= 1
|
|
|
|
// --- chained assignment ---
|
|
var ch1, ch2
|
|
ch1 = ch2 = 42
|
|
|
|
// --- property access ---
|
|
var obj = {a: {b: {c: 1}}, items: [10, 20, 30]}
|
|
var dot_access = obj.a
|
|
var dot_chain = obj.a.b.c
|
|
var bracket_access = obj["a"]
|
|
var bracket_dynamic = obj["it" + "ems"]
|
|
var bracket_index = obj.items[1]
|
|
|
|
// --- optional chaining ---
|
|
var opt_obj = {x: {y: 1}}
|
|
var opt_prop = opt_obj?.x
|
|
var opt_deep = opt_obj?.x?.y
|
|
var opt_null = null?.foo
|
|
var opt_bracket = opt_obj?.["x"]
|
|
var opt_call_obj = {f: function() { return 1 }}
|
|
var opt_call = opt_call_obj?.f?.()
|
|
|
|
// --- function declarations ---
|
|
function add(a, b) {
|
|
return a + b
|
|
}
|
|
|
|
function no_params() {
|
|
return 42
|
|
}
|
|
|
|
function with_default(x = 10, y = 20) {
|
|
return x + y
|
|
}
|
|
|
|
// --- function expressions ---
|
|
var func_expr = function(x) { return x * 2 }
|
|
var func_named = function multiply(x, y) { return x * y }
|
|
|
|
// --- arrow functions (all forms) ---
|
|
var arrow_no_param = () => 0
|
|
var arrow_one = x => x + 1
|
|
var arrow_multi = (a, b) => a + b
|
|
var arrow_block = (a, b) => { return a + b }
|
|
var arrow_default = (x = 1, y = 2) => x + y
|
|
var arrow_default_expr = (x = 1 + 2, y = arr_simple[0]) => x + y
|
|
|
|
// --- closures ---
|
|
function make_counter() {
|
|
var count = 0
|
|
return function() {
|
|
count += 1
|
|
return count
|
|
}
|
|
}
|
|
|
|
function outer_fn() {
|
|
var x = 10
|
|
function middle() {
|
|
var y = 20
|
|
function inner() {
|
|
return x + y
|
|
}
|
|
return inner()
|
|
}
|
|
return middle()
|
|
}
|
|
|
|
// --- this in methods ---
|
|
var counter = {
|
|
val: 0,
|
|
inc() { this.val += 1 },
|
|
get() { return this.val }
|
|
}
|
|
|
|
// --- if/else/else-if ---
|
|
var if_result
|
|
if (b > 0) {
|
|
if_result = "positive"
|
|
} else if (b == 0) {
|
|
if_result = "zero"
|
|
} else {
|
|
if_result = "negative"
|
|
}
|
|
|
|
// --- while loop ---
|
|
var w = 0
|
|
while (w < 5) {
|
|
w += 1
|
|
}
|
|
|
|
// --- do-while loop ---
|
|
var dw = 0
|
|
do {
|
|
dw += 1
|
|
} while (dw < 3)
|
|
|
|
// --- for loop ---
|
|
var f_sum = 0
|
|
for (var i = 0; i < 10; i++) {
|
|
f_sum += i
|
|
}
|
|
|
|
// --- for loop with break ---
|
|
var fb = 0
|
|
for (var j = 0; j < 100; j++) {
|
|
if (j == 5) break
|
|
fb = j
|
|
}
|
|
|
|
// --- for loop with continue ---
|
|
var fc = 0
|
|
for (var k = 0; k < 10; k++) {
|
|
if (k % 2 == 0) continue
|
|
fc += k
|
|
}
|
|
|
|
// --- labeled break ---
|
|
outer: for (var x = 0; x < 3; x++) {
|
|
for (var y = 0; y < 3; y++) {
|
|
if (y == 1) break outer
|
|
}
|
|
}
|
|
|
|
// --- labeled continue ---
|
|
var lc = 0
|
|
loop: for (var m = 0; m < 3; m++) {
|
|
for (var n = 0; n < 3; n++) {
|
|
if (n == 1) continue loop
|
|
lc += 1
|
|
}
|
|
}
|
|
|
|
// --- try/catch/finally ---
|
|
var tc
|
|
try {
|
|
throw "error"
|
|
} catch (e) {
|
|
tc = e
|
|
}
|
|
|
|
var tcf = 0
|
|
try {
|
|
throw "err"
|
|
} catch (e) {
|
|
tcf = 1
|
|
} finally {
|
|
tcf += 10
|
|
}
|
|
|
|
// --- try/finally (no catch) ---
|
|
var tf = 0
|
|
try {
|
|
tf = 1
|
|
} finally {
|
|
tf += 1
|
|
}
|
|
|
|
// --- delete operator ---
|
|
var del_obj = {a: 1, b: 2}
|
|
delete del_obj.a
|
|
|
|
// --- in operator ---
|
|
var in_result = "b" in del_obj
|
|
|
|
// --- go statement ---
|
|
function async_task() { return 1 }
|
|
function caller() { go async_task() }
|
|
|
|
// --- IIFE ---
|
|
var iife = (function() { return 99 })()
|
|
|
|
// --- recursive function ---
|
|
function factorial(n) {
|
|
if (n <= 1) return 1
|
|
return n * factorial(n - 1)
|
|
}
|
|
|
|
// --- mutually recursive functions ---
|
|
function is_even(n) {
|
|
if (n == 0) return true
|
|
return is_odd(n - 1)
|
|
}
|
|
function is_odd(n) {
|
|
if (n == 0) return false
|
|
return is_even(n - 1)
|
|
}
|
|
|
|
// --- block scoping ---
|
|
var block_val = 1
|
|
{
|
|
var block_val = 2
|
|
}
|
|
|
|
// --- nested blocks ---
|
|
{
|
|
var nb = 1
|
|
{
|
|
var nb2 = nb + 1
|
|
{
|
|
var nb3 = nb2 + 1
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- empty statement ---
|
|
;
|
|
|
|
// --- parenthesized expression for precedence ---
|
|
var prec = (1 + 2) * (3 + 4)
|
|
|
|
// --- complex expressions ---
|
|
var complex = arr_simple[0] + rec_simple.x * (b > 0 ? 2 : 1)
|
|
|
|
// --- operator precedence chain ---
|
|
var prec_chain = 1 + 2 * 3 ** 2 - 4 / 2 % 3
|
|
|
|
// --- regex literals ---
|
|
var re = /hello/
|
|
var re_flags = /world/gi
|
|
|
|
// --- line comment at end ---
|
|
var end = 1 // done
|