postfix/prefix operators handled correctly
This commit is contained in:
BIN
mcode.mach
BIN
mcode.mach
Binary file not shown.
64
parse.cm
64
parse.cm
@@ -499,6 +499,9 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
var index = null
|
||||
var arg = null
|
||||
var args_list = null
|
||||
var one_node = null
|
||||
var binop_node = null
|
||||
var op = null
|
||||
if (node == null) return null
|
||||
while (true) {
|
||||
start = tok
|
||||
@@ -574,6 +577,10 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
var node = null
|
||||
var expr = null
|
||||
var k = tok.kind
|
||||
var operand = null
|
||||
var one_node = null
|
||||
var binop_node = null
|
||||
var op = null
|
||||
if (k == "!") {
|
||||
advance()
|
||||
node = ast_node("!", start)
|
||||
@@ -602,19 +609,22 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
ast_node_end(node)
|
||||
return node
|
||||
}
|
||||
if (k == "++") {
|
||||
if (k == "++" || k == "--") {
|
||||
advance()
|
||||
node = ast_node("++", start)
|
||||
node.expression = parse_unary()
|
||||
node.postfix = false
|
||||
ast_node_end(node)
|
||||
return node
|
||||
}
|
||||
if (k == "--") {
|
||||
advance()
|
||||
node = ast_node("--", start)
|
||||
node.expression = parse_unary()
|
||||
node.postfix = false
|
||||
operand = parse_unary()
|
||||
one_node = ast_node("number", start)
|
||||
one_node.number = 1
|
||||
one_node.value = "1"
|
||||
ast_node_end(one_node)
|
||||
op = "+"
|
||||
if (k == "--") op = "-"
|
||||
binop_node = ast_node(op, start)
|
||||
binop_node.left = operand
|
||||
binop_node.right = one_node
|
||||
ast_node_end(binop_node)
|
||||
node = ast_node("assign", start)
|
||||
node.left = operand
|
||||
node.right = binop_node
|
||||
ast_node_end(node)
|
||||
return node
|
||||
}
|
||||
@@ -699,6 +709,13 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
"&&=": "&&=", "||=": "||="
|
||||
}
|
||||
|
||||
var compound_binop = {
|
||||
"+=": "+", "-=": "-", "*=": "*", "/=": "/", "%=": "%",
|
||||
"<<=": "<<", ">>=": ">>", ">>>=": ">>>",
|
||||
"&=": "&", "^=": "^", "|=": "|", "**=": "**",
|
||||
"&&=": "&&", "||=": "||"
|
||||
}
|
||||
|
||||
parse_assign = function(unused) {
|
||||
var left_node = parse_ternary()
|
||||
var start = null
|
||||
@@ -707,6 +724,8 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
var node = null
|
||||
var left_kind = null
|
||||
var right_kind = null
|
||||
var binop = null
|
||||
var binop_node = null
|
||||
if (left_node == null) return null
|
||||
start = tok
|
||||
kind = assign_ops[tok.kind]
|
||||
@@ -719,12 +738,23 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
|
||||
advance()
|
||||
right_node = parse_assign()
|
||||
node = ast_node(kind, start)
|
||||
node.left = left_node
|
||||
node.right = right_node
|
||||
|
||||
if (left_node.kind == "[" && left_node.right == null) node.push = true
|
||||
if (right_node != null && right_node.kind == "[" && right_node.right == null) node.pop = true
|
||||
binop = compound_binop[kind]
|
||||
if (binop != null) {
|
||||
binop_node = ast_node(binop, start)
|
||||
binop_node.left = left_node
|
||||
binop_node.right = right_node
|
||||
ast_node_end(binop_node)
|
||||
node = ast_node("assign", start)
|
||||
node.left = left_node
|
||||
node.right = binop_node
|
||||
} else {
|
||||
node = ast_node(kind, start)
|
||||
node.left = left_node
|
||||
node.right = right_node
|
||||
if (left_node.kind == "[" && left_node.right == null) node.push = true
|
||||
if (right_node != null && right_node.kind == "[" && right_node.right == null) node.pop = true
|
||||
}
|
||||
|
||||
ast_node_end(node)
|
||||
return node
|
||||
|
||||
BIN
parse.mach
BIN
parse.mach
Binary file not shown.
191
vm_suite.ce
191
vm_suite.ce
@@ -1058,6 +1058,197 @@ run("modulo equals", function() {
|
||||
if (x != 1) fail("modulo equals failed")
|
||||
})
|
||||
|
||||
// ============================================================================
|
||||
// COMPOUND ASSIGNMENT ON PROPERTIES
|
||||
// ============================================================================
|
||||
|
||||
run("plus equals on property", function() {
|
||||
var obj = {x: 10}
|
||||
obj.x += 5
|
||||
if (obj.x != 15) fail("obj.x += 5")
|
||||
})
|
||||
|
||||
run("minus equals on property", function() {
|
||||
var obj = {x: 10}
|
||||
obj.x -= 3
|
||||
if (obj.x != 7) fail("obj.x -= 3")
|
||||
})
|
||||
|
||||
run("times equals on property", function() {
|
||||
var obj = {x: 4}
|
||||
obj.x *= 3
|
||||
if (obj.x != 12) fail("obj.x *= 3")
|
||||
})
|
||||
|
||||
run("divide equals on property", function() {
|
||||
var obj = {x: 12}
|
||||
obj.x /= 3
|
||||
if (obj.x != 4) fail("obj.x /= 3")
|
||||
})
|
||||
|
||||
run("modulo equals on property", function() {
|
||||
var obj = {x: 10}
|
||||
obj.x %= 3
|
||||
if (obj.x != 1) fail("obj.x %= 3")
|
||||
})
|
||||
|
||||
run("compound assign preserves other properties", function() {
|
||||
var obj = {x: 10, y: 20}
|
||||
obj.x += 5
|
||||
if (obj.x != 15) fail("x wrong")
|
||||
if (obj.y != 20) fail("y changed")
|
||||
})
|
||||
|
||||
run("compound assign nested property", function() {
|
||||
var obj = {inner: {val: 10}}
|
||||
obj.inner.val += 5
|
||||
if (obj.inner.val != 15) fail("nested += failed")
|
||||
})
|
||||
|
||||
run("compound assign chained", function() {
|
||||
var obj = {x: 1}
|
||||
obj.x += 2
|
||||
obj.x += 3
|
||||
obj.x += 4
|
||||
if (obj.x != 10) fail("chained += failed")
|
||||
})
|
||||
|
||||
// ============================================================================
|
||||
// COMPOUND ASSIGNMENT ON ARRAY ELEMENTS
|
||||
// ============================================================================
|
||||
|
||||
run("plus equals on array element", function() {
|
||||
var arr = [100, 200, 300]
|
||||
arr[0] += 50
|
||||
if (arr[0] != 150) fail("arr[0] += 50")
|
||||
})
|
||||
|
||||
run("minus equals on array element", function() {
|
||||
var arr = [100, 200, 300]
|
||||
arr[1] -= 50
|
||||
if (arr[1] != 150) fail("arr[1] -= 50")
|
||||
})
|
||||
|
||||
run("times equals on array element", function() {
|
||||
var arr = [5]
|
||||
arr[0] *= 6
|
||||
if (arr[0] != 30) fail("arr[0] *= 6")
|
||||
})
|
||||
|
||||
run("compound assign computed property", function() {
|
||||
var obj = {a: 10, b: 20}
|
||||
var key = "a"
|
||||
obj[key] += 5
|
||||
if (obj.a != 15) fail("obj[key] += 5")
|
||||
})
|
||||
|
||||
run("compound assign array element preserves others", function() {
|
||||
var arr = [10, 20, 30]
|
||||
arr[1] += 5
|
||||
if (arr[0] != 10) fail("arr[0] changed")
|
||||
if (arr[1] != 25) fail("arr[1] wrong")
|
||||
if (arr[2] != 30) fail("arr[2] changed")
|
||||
})
|
||||
|
||||
// ============================================================================
|
||||
// PREFIX INCREMENT/DECREMENT ON PROPERTIES
|
||||
// ============================================================================
|
||||
|
||||
run("prefix increment on property", function() {
|
||||
var obj = {x: 5}
|
||||
var y = ++obj.x
|
||||
if (y != 6) fail("return value")
|
||||
if (obj.x != 6) fail("side effect")
|
||||
})
|
||||
|
||||
run("prefix decrement on property", function() {
|
||||
var obj = {x: 5}
|
||||
var y = --obj.x
|
||||
if (y != 4) fail("return value")
|
||||
if (obj.x != 4) fail("side effect")
|
||||
})
|
||||
|
||||
run("prefix increment on array element", function() {
|
||||
var arr = [10]
|
||||
var y = ++arr[0]
|
||||
if (y != 11) fail("return value")
|
||||
if (arr[0] != 11) fail("side effect")
|
||||
})
|
||||
|
||||
run("prefix decrement on array element", function() {
|
||||
var arr = [10]
|
||||
var y = --arr[0]
|
||||
if (y != 9) fail("return value")
|
||||
if (arr[0] != 9) fail("side effect")
|
||||
})
|
||||
|
||||
// ============================================================================
|
||||
// INCREMENT/DECREMENT IN LOOPS AND EXPRESSIONS
|
||||
// ============================================================================
|
||||
|
||||
run("compound assign in for loop", function() {
|
||||
var sum = 0
|
||||
var i = 0
|
||||
for (i = 0; i < 5; i++) {
|
||||
sum += i
|
||||
}
|
||||
if (sum != 10) fail("sum should be 10")
|
||||
})
|
||||
|
||||
run("compound assign property in loop", function() {
|
||||
var obj = {count: 0}
|
||||
var i = 0
|
||||
for (i = 0; i < 5; i++) {
|
||||
obj.count += 1
|
||||
}
|
||||
if (obj.count != 5) fail("count should be 5")
|
||||
})
|
||||
|
||||
run("prefix increment in expression", function() {
|
||||
var x = 5
|
||||
var y = 10 + ++x
|
||||
if (y != 16) fail("10 + ++x should be 16")
|
||||
if (x != 6) fail("x should be 6")
|
||||
})
|
||||
|
||||
run("compound assign bitwise and-equals", function() {
|
||||
var x = 15
|
||||
x &= 6
|
||||
if (x != 6) fail("15 & 6 should be 6")
|
||||
})
|
||||
|
||||
run("compound assign bitwise or-equals", function() {
|
||||
var x = 5
|
||||
x |= 3
|
||||
if (x != 7) fail("5 | 3 should be 7")
|
||||
})
|
||||
|
||||
run("compound assign bitwise xor-equals", function() {
|
||||
var x = 5
|
||||
x ^= 3
|
||||
if (x != 6) fail("5 ^ 3 should be 6")
|
||||
})
|
||||
|
||||
run("compound assign left shift-equals", function() {
|
||||
var x = 1
|
||||
x <<= 3
|
||||
if (x != 8) fail("1 << 3 should be 8")
|
||||
})
|
||||
|
||||
run("compound assign right shift-equals", function() {
|
||||
var x = 16
|
||||
x >>= 2
|
||||
if (x != 4) fail("16 >> 2 should be 4")
|
||||
})
|
||||
|
||||
run("compound assign bitwise on property", function() {
|
||||
var obj = {flags: 5}
|
||||
obj.flags |= 8
|
||||
if (obj.flags != 13) fail("5 | 8 should be 13")
|
||||
obj.flags &= 12
|
||||
if (obj.flags != 12) fail("13 & 12 should be 12")
|
||||
})
|
||||
|
||||
// ============================================================================
|
||||
// EDGE CASES AND SPECIAL VALUES
|
||||
// ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user