Changeset - 2dc5ec5e11be
[Not reviewed]
default
0 2 0
Laman - 2 years ago 2023-01-01 21:11:21

AssignmentExpression
2 files changed with 28 insertions and 2 deletions:
0 comments (0 inline, 0 general)
src/jasinta.py
Show inline comments
 
@@ -40,48 +40,61 @@ class ExpressionStatement:
 
	def eval(self, context):
 
		evaluate(self.node["expression"], context)
 

	
 

	
 
class CallExpression:
 
	def __init__(self, node):
 
		self.node = node
 

	
 
	def eval(self, context):
 
		callee = evaluate(self.node["callee"], context)
 
		arguments = [evaluate(arg, context) for arg in self.node["arguments"]]
 
		return callee(*arguments)
 

	
 

	
 
class MemberExpression:
 
	def __init__(self, node):
 
		self.node = node
 

	
 
	def eval(self, context):
 
		obj = evaluate(self.node["object"], context)
 
		prop = evaluate(self.node["property"], [obj])
 
		return prop
 

	
 

	
 
class AssignmentExpression:
 
	def __init__(self, node):
 
		self.node = node
 

	
 
	def eval(self, context):
 
		left = evaluate(self.node["left"], context)
 
		right = evaluate(self.node["right"], context)
 
		if self.node["operator"] == "+=":
 
			left.val += right.val
 
		else:
 
			raise NotImplementedError
 

	
 

	
 
class BinaryExpression:
 
	def __init__(self, node):
 
		self.node = node
 

	
 
	def eval(self, context):
 
		left = evaluate(self.node["left"], context)
 
		right = evaluate(self.node["right"], context)
 

	
 
		# in fact this doesn't follow JavaScript "+" semantics
 
		if self.node["operator"] == "+":
 
			return Number(left.val+right.val)
 
		else:
 
			raise NotImplementedError
 

	
 

	
 
class EmptyStatement:
 
	def __init__(self, node):
 
		pass
 

	
 
	def eval(self, context):
 
		pass
 

	
 

	
 
class VariableDeclaration:
 
@@ -103,31 +116,31 @@ class VariableDeclarator:
 
		if self.node["id"]["type"] == "Identifier":
 
			name = self.node["id"]["name"]
 
			context[-1][name] = value
 
		else:
 
			raise NotImplementedError
 

	
 

	
 
class Literal:
 
	def __init__(self, node):
 
		self.node = node
 

	
 
	def eval(self, context):
 
		val = self.node["value"]
 

	
 
		if isinstance(val, float):
 
			if int(val) == val:
 
				return Number(int(val))
 
			else:
 
				return Number(val)
 
		else:
 
			raise NotImplementedError
 

	
 

	
 
node_index = {cls.__name__: cls for cls in [
 
	Program, ExpressionStatement, CallExpression, MemberExpression, EmptyStatement, BinaryExpression,
 
	VariableDeclaration, VariableDeclarator, Literal
 
	Program, ExpressionStatement, CallExpression, MemberExpression, EmptyStatement, AssignmentExpression,
 
	BinaryExpression, VariableDeclaration, VariableDeclarator, Literal
 
]}
 

	
 

	
 
def interpret(parse_tree):
 
	return evaluate(parse_tree, [stdlib])
tests/test_jasinta.py
Show inline comments
 
from unittest import TestCase
 
from unittest.mock import patch
 

	
 
from pyjsparser import parse
 

	
 
from jasinta import interpret
 

	
 

	
 
class TestBasicAddition(TestCase):
 
	@patch("builtins.print")
 
	def test_interpret(self, mock_print):
 
		s = """var a=3;
 
var b=1;
 
var c=a+b;
 
document.write(c);"""
 

	
 
		interpret(parse(s))
 
		mock_print.assert_called_with(4)
 

	
 

	
 
class TestAssignment(TestCase):
 
	@patch("builtins.print")
 
	def test_interpret(self, mock_print):
 
		s = """var a=1;
 
var b=1;
 
a+=b;
 
b+=a;
 
document.write(b);"""
 

	
 
		interpret(parse(s))
 
		mock_print.assert_called_with(3)
0 comments (0 inline, 0 general)