Files @ 2dc5ec5e11be
Branch filter:

Location: Jasinta/src/jasinta.py

Laman
AssignmentExpression
from std import lib as stdlib, Number


class Undefined:
	pass


def evaluate(node, context):
	if node is None:
		return None

	node_type = node["type"]
	# retrieve an already existing object from the context
	if node_type == "Identifier":
		for ctx in reversed(context):
			if node["name"] in ctx:
				return ctx[node["name"]]
		return Undefined

	# create a new object
	cls = node_index[node_type]
	obj = cls(node)
	return obj.eval(context)


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

	def eval(self, context):
		program_context = [*context, dict()]
		for node in self.node["body"]:
			evaluate(node, program_context)


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

	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:
	def __init__(self, node):
		self.node = node

	def eval(self, context):
		for node in self.node["declarations"]:
			evaluate(node, context)


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

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

		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, AssignmentExpression,
	BinaryExpression, VariableDeclaration, VariableDeclarator, Literal
]}


def interpret(parse_tree):
	return evaluate(parse_tree, [stdlib])