implement double
This commit is contained in:
@ -36,6 +36,8 @@ object inttrait:
|
||||
self $int_tobool
|
||||
def tostr:
|
||||
self $int_tostr
|
||||
def todouble:
|
||||
self $int_todouble
|
||||
|
||||
# Project: Boolean
|
||||
object booltrait:
|
||||
@ -50,6 +52,8 @@ object booltrait:
|
||||
self $bool_toint
|
||||
def tostr:
|
||||
self $bool_tostr
|
||||
def todouble:
|
||||
self $bool_todouble
|
||||
|
||||
# Project: String
|
||||
object strtrait:
|
||||
@ -66,3 +70,25 @@ object strtrait:
|
||||
self $str_tobool
|
||||
def toint:
|
||||
self $str_toint
|
||||
def todouble:
|
||||
self $str_todouble
|
||||
|
||||
# Project: Double
|
||||
object doubletrait:
|
||||
def eq(other):
|
||||
self $double_eq(other)
|
||||
def add(other):
|
||||
self $double_add(other)
|
||||
def sub(other):
|
||||
self $double_sub(other)
|
||||
def mul(other):
|
||||
self $double_mul(other)
|
||||
def div(other):
|
||||
self $double_div(other)
|
||||
|
||||
def toint:
|
||||
self $double_toint
|
||||
def tobool:
|
||||
self $double_tobool
|
||||
def tostr:
|
||||
self $double_tostr
|
||||
|
@ -72,6 +72,10 @@ class Interpreter(object):
|
||||
value = bytecode.symbols[oparg]
|
||||
w_value = self.space.newstring(value)
|
||||
stack.append(w_value)
|
||||
elif opcode == compile.DOUBLE_LITERAL: # Project: Double
|
||||
value = bytecode.symbols[oparg]
|
||||
w_value = self.space.newdouble(value)
|
||||
stack.append(w_value)
|
||||
elif opcode == compile.MAKE_FUNCTION:
|
||||
bc = bytecode.subbytecodes[oparg]
|
||||
w_method = self.space.definemethod(name=bc.name, code=bc, w_target=w_context)
|
||||
|
@ -112,6 +112,7 @@ import simpleast
|
||||
BOOL_LITERAL = 1 # 1 or 0 # Project: Boolean
|
||||
INT_LITERAL = 2 # integer value
|
||||
STRING_LITERAL = 3 # Project: String
|
||||
DOUBLE_LITERAL = 17 # Project: Double
|
||||
ASSIGNMENT = 4 # index of attrname
|
||||
METHOD_LOOKUP = 5 # index of method name
|
||||
METHOD_CALL = 6 # number of arguments
|
||||
@ -192,6 +193,7 @@ def compile(ast, argumentnames=[], name=None):
|
||||
stack_effects = {
|
||||
BOOL_LITERAL: 1, # Project: Boolean
|
||||
STRING_LITERAL: 1, # Project: String
|
||||
DOUBLE_LITERAL: 1, # Project: Double
|
||||
INT_LITERAL: 1,
|
||||
ASSIGNMENT: -1,
|
||||
METHOD_LOOKUP: 1,
|
||||
@ -295,6 +297,10 @@ class Compiler(object):
|
||||
def compile_StringLiteral(self, astnode, needsresult):
|
||||
self.emit(STRING_LITERAL, self.lookup_symbol(astnode.value)) # save string value to symboltable
|
||||
|
||||
# Project: Double
|
||||
def compile_DoubleLiteral(self, astnode, needsresult):
|
||||
self.emit(DOUBLE_LITERAL, self.lookup_symbol(astnode.value))
|
||||
|
||||
def compile_ImplicitSelf(self, astnode, needsresult):
|
||||
self.emit(IMPLICIT_SELF)
|
||||
|
||||
|
@ -2,7 +2,6 @@ from c3computation import compute_C3_mro as c3
|
||||
|
||||
|
||||
class AbstractObject(object):
|
||||
|
||||
def call(self, w_receiver, args_w):
|
||||
return self
|
||||
|
||||
@ -26,7 +25,6 @@ class AbstractObject(object):
|
||||
|
||||
|
||||
class W_NormalObject(AbstractObject):
|
||||
|
||||
def __init__(self, name=None, slots=None, parents=None, space=None):
|
||||
self.space = space
|
||||
self.name = name
|
||||
@ -131,12 +129,37 @@ class W_String(AbstractObject):
|
||||
|
||||
__repr__ = __str__
|
||||
|
||||
def istrue(self):
|
||||
return self.value != 0.
|
||||
|
||||
|
||||
# Project: Double
|
||||
class W_Double(W_NormalObject):
|
||||
def __init__(self, value, space=None):
|
||||
self.value = float(value)
|
||||
self.space = space
|
||||
self.__trait = "doubletrait"
|
||||
|
||||
def getparents(self):
|
||||
if self.space is None:
|
||||
return [] # for tests
|
||||
trait = self.space.getbuiltin(self.__trait)
|
||||
assert trait is not None, 'O_o bogus state'
|
||||
return [trait]
|
||||
|
||||
def hasslot(self, name):
|
||||
return False
|
||||
|
||||
def __str__(self):
|
||||
return str(self.value)
|
||||
|
||||
__repr__ = __str__
|
||||
|
||||
def istrue(self):
|
||||
return self.value != ""
|
||||
|
||||
|
||||
class W_Method(W_NormalObject):
|
||||
|
||||
def __init__(self, code, *args, **kwargs):
|
||||
super(W_Method, self).__init__(*args, **kwargs)
|
||||
self.code = code
|
||||
|
@ -1,4 +1,4 @@
|
||||
from objmodel import W_Integer, W_Boolean, W_String
|
||||
from objmodel import W_Integer, W_Boolean, W_String, W_Double
|
||||
from objmodel import W_Method
|
||||
from objmodel import W_NormalObject
|
||||
|
||||
@ -57,6 +57,10 @@ class ObjectSpace(object):
|
||||
def newstring(self, value):
|
||||
return W_String(value, space=self)
|
||||
|
||||
# Project: Double
|
||||
def newdouble(self, value):
|
||||
return W_Double(value, space=self)
|
||||
|
||||
def definemethod(self, name, code, w_target):
|
||||
w_meth = W_Method(code, name=name,
|
||||
slots={'__parent__': w_target},
|
||||
|
@ -16,12 +16,10 @@ def primitive(name, unwrap_spec, wrap_spec): # decorator arguments
|
||||
|
||||
unwrapped_args = ()
|
||||
for t, arg in zip(unwrap_spec, args): # unpack values from simple-objects
|
||||
if t is int:
|
||||
if t in [int, str, float]: # Project: Double, String
|
||||
unwrapped_args += (arg.value,)
|
||||
elif t is bool: # Project: Boolean
|
||||
unwrapped_args += (bool(arg.value),) # isn't really necessary because "1 or 0" is also valid
|
||||
elif t is str: # Project: String
|
||||
unwrapped_args += (arg.value,)
|
||||
else:
|
||||
unwrapped_args += (arg,)
|
||||
|
||||
@ -33,6 +31,8 @@ def primitive(name, unwrap_spec, wrap_spec): # decorator arguments
|
||||
return space.newbool(result)
|
||||
elif wrap_spec is str: # Project: String
|
||||
return space.newstring(result)
|
||||
elif wrap_spec is float: # Project: Double
|
||||
return space.newdouble(result)
|
||||
return result
|
||||
|
||||
unwrapper.__qualname__ = name
|
||||
@ -93,6 +93,11 @@ def simple_int_tobstr(a):
|
||||
return a
|
||||
|
||||
|
||||
@primitive("int_todouble", [int], float)
|
||||
def simple_int_tobdouble(a):
|
||||
return a
|
||||
|
||||
|
||||
# Project: Boolean
|
||||
@primitive("bool_and", [bool, bool], bool)
|
||||
def simple_bool_and(a, b):
|
||||
@ -119,6 +124,11 @@ def simple_bool_tostr(a):
|
||||
return str(a).lower()
|
||||
|
||||
|
||||
@primitive("bool_todouble", [bool], float)
|
||||
def simple_bool_todouble(a):
|
||||
return a
|
||||
|
||||
|
||||
# bool stuff for int
|
||||
@primitive("int_eq", [int, int], bool)
|
||||
def simple_int_eq(a, b):
|
||||
@ -174,3 +184,49 @@ def simple_str_toint(a):
|
||||
@primitive("str_tobool", [str], bool)
|
||||
def simple_str_tobool(a):
|
||||
return a == "true"
|
||||
|
||||
|
||||
@primitive("str_todouble", [str], float)
|
||||
def simple_str_todouble(a):
|
||||
return a
|
||||
|
||||
|
||||
# Project: Double
|
||||
@primitive("double_eq", [float, float], bool)
|
||||
def simple_double_eq(a, b):
|
||||
return a == b
|
||||
|
||||
|
||||
@primitive("double_add", [float, float], float)
|
||||
def simple_double_add(a, b):
|
||||
return a + b
|
||||
|
||||
|
||||
@primitive("double_sub", [float, float], float)
|
||||
def simple_double_sub(a, b):
|
||||
return a - b
|
||||
|
||||
|
||||
@primitive("double_mul", [float, float], float)
|
||||
def simple_double_mul(a, b):
|
||||
return a * b
|
||||
|
||||
|
||||
@primitive("double_div", [float, float], float)
|
||||
def simple_double_div(a, b):
|
||||
return a / b
|
||||
|
||||
|
||||
@primitive("double_toint", [float], int)
|
||||
def simple_double_toint(a):
|
||||
return a
|
||||
|
||||
|
||||
@primitive("double_tobool", [float], bool)
|
||||
def simple_double_tobool(a):
|
||||
return a
|
||||
|
||||
|
||||
@primitive("double_tostr", [float], str)
|
||||
def simple_double_tostr(a):
|
||||
return a
|
||||
|
@ -113,6 +113,16 @@ class StringLiteral(Expression):
|
||||
self.value = str(value)
|
||||
|
||||
|
||||
# Project: Double
|
||||
class DoubleLiteral(Expression):
|
||||
""" A double literal (like "1.0", ".0", "1.", "+1.0") """
|
||||
|
||||
attrs = ["value"]
|
||||
|
||||
def __init__(self, value):
|
||||
self.value = float(value)
|
||||
|
||||
|
||||
class MethodCall(Expression):
|
||||
""" A call to a method with name 'methodname' on 'receiver' with
|
||||
'arguments' (which is a list of expression ASTs).
|
||||
|
@ -158,11 +158,17 @@ OpenBracket = r'[\[\(\{]'
|
||||
CloseBracket = r'[\]\)\}]'
|
||||
|
||||
# ____________________________________________________________
|
||||
# Project: Boolean, String
|
||||
# Project: Boolean, String, Double
|
||||
|
||||
Boolean = group(r'true', r'false')
|
||||
Boolean = r"true|false"
|
||||
String = group(make_single_string(r"\'"), make_single_string(r'\"'))
|
||||
|
||||
_sign = r"([+-])?"
|
||||
_int = r"(([1-9][0-9]*)|0)"
|
||||
_dec = r"(([0-9]*[1-9])|0)"
|
||||
Double = group(_sign + group(_int, r"") + r"\." + _dec,
|
||||
_sign + _int + r"\." + group(_dec, r""))
|
||||
|
||||
# ____________________________________________________________
|
||||
# Project: Sugar
|
||||
|
||||
@ -182,8 +188,9 @@ While = r'while'
|
||||
Def = r'def'
|
||||
Object = r'object'
|
||||
|
||||
tokens = ["If", "Else", "While", "Def", "Object", "Number", "Ignore",
|
||||
"String", "Boolean", # Project: Boolean, String
|
||||
tokens = ["If", "Else", "While", "Def", "Object", "Ignore",
|
||||
"String", "Boolean", "Double", # Project: Boolean, String, Double
|
||||
"Number", # after Double
|
||||
"NewlineAndWhitespace", "OpenBracket", "CloseBracket", "Comma", "Assign", "Colon",
|
||||
"Increment", "Plus", "Minus", "Multiply", "Divide", "Modulo", # Project: Sugar
|
||||
"Name", "PrimitiveName"]
|
||||
|
@ -6,7 +6,7 @@ from simplelexer import lex
|
||||
import simpleast
|
||||
|
||||
pg = ParserGenerator(["If", "Else", "While", "Def", "Object", "Number",
|
||||
"String", "Boolean", # Project: Boolean, String
|
||||
"String", "Boolean", "Double", # Project: Boolean, String, Double
|
||||
"Name", "Indent", "Dedent", "Newline", "OpenBracket",
|
||||
"CloseBracket", "Comma", "Assign", "Colon",
|
||||
"Increment", "Plus", "Minus", "Multiply", "Divide", "Modulo", # Project: Sugar
|
||||
@ -210,6 +210,12 @@ def string_expression(stmt):
|
||||
return simpleast.StringLiteral(stmt[0].value[1:-1]) # cut off delimiters
|
||||
|
||||
|
||||
# Project: Double
|
||||
@pg.production("basic_expression : Double")
|
||||
def double_expression(stmt):
|
||||
return simpleast.DoubleLiteral(stmt[0].value)
|
||||
|
||||
|
||||
@pg.production("basic_expression : implicitselfmethodcall")
|
||||
def implicitselfmethodcall(call):
|
||||
methodcall = call[0]
|
||||
|
@ -1,8 +1,26 @@
|
||||
from rply import Token
|
||||
|
||||
from simpleast import Program, ExprStatement, StringLiteral, ImplicitSelf, Assignment, DoubleLiteral
|
||||
from simplelexer import lex
|
||||
from simpleparser import parse
|
||||
from objmodel import W_Integer
|
||||
from objmodel import W_Integer, W_Double
|
||||
from interpreter import Interpreter
|
||||
|
||||
|
||||
def test_basic_double_lexing():
|
||||
assert lex("0.1")[0] == Token("Double", "0.1")
|
||||
assert lex(".1")[0] == Token("Double", ".1")
|
||||
assert lex("1.")[0] == Token("Double", "1.")
|
||||
assert lex("-5.5")[0] == Token("Double", "-5.5")
|
||||
assert lex("-.5")[0] == Token("Double", "-.5")
|
||||
assert lex("x = 0.0005")[:3] == [Token("Name", "x"), Token("Assign", "="), Token("Double", "0.0005")]
|
||||
|
||||
|
||||
def test_basic_double_parsing():
|
||||
assert parse("1.0") == Program([ExprStatement(DoubleLiteral("1.0"))])
|
||||
assert parse("x = -.1") == Program([Assignment(ImplicitSelf(), "x", DoubleLiteral("-0.1"))])
|
||||
|
||||
|
||||
def test_double_assignment():
|
||||
ast = parse("""
|
||||
x = 1.5
|
||||
@ -15,7 +33,25 @@ x = 1.5
|
||||
assert w_model.getvalue("x").value == 1.5
|
||||
|
||||
|
||||
def test_double_operations():
|
||||
def test_double_addition_subtraction():
|
||||
ast = parse("""
|
||||
x = 2.5 sub(2.4)
|
||||
y = 2.5 add(2.4)
|
||||
z = 3 sub(2.5)
|
||||
""")
|
||||
interpreter = Interpreter()
|
||||
w_model = interpreter.make_module()
|
||||
interpreter.eval(ast, w_model)
|
||||
|
||||
assert isinstance(w_model.getvalue("x"), W_Double)
|
||||
assert w_model.getvalue("x").value == (2.5 - 2.4)
|
||||
assert isinstance(w_model.getvalue("y"), W_Double)
|
||||
assert w_model.getvalue("y").value == (2.5 + 2.4)
|
||||
assert isinstance(w_model.getvalue("z"), W_Integer)
|
||||
assert w_model.getvalue("z").value == 0
|
||||
|
||||
|
||||
def test_double_division():
|
||||
ast = parse("""
|
||||
x = 3 div(2)
|
||||
y = 3 div(2.0)
|
||||
@ -33,6 +69,24 @@ z = 3.0 div(2.0)
|
||||
assert w_model.getvalue("z").value == 1.5
|
||||
|
||||
|
||||
def test_double_multiplication():
|
||||
ast = parse("""
|
||||
x = 3.3 mul(3.0)
|
||||
y = 3.3 mul(3)
|
||||
z = 3 mul(3.3)
|
||||
""")
|
||||
interpreter = Interpreter()
|
||||
w_model = interpreter.make_module()
|
||||
interpreter.eval(ast, w_model)
|
||||
|
||||
assert isinstance(w_model.getvalue("x"), W_Double)
|
||||
assert w_model.getvalue("x").value == (3.3 * 3.0)
|
||||
assert isinstance(w_model.getvalue("y"), W_Double)
|
||||
assert w_model.getvalue("y").value == (3.3 * 3)
|
||||
assert isinstance(w_model.getvalue("z"), W_Integer)
|
||||
assert w_model.getvalue("z").value == 9
|
||||
|
||||
|
||||
def test_double_conversion():
|
||||
ast = parse("""
|
||||
x = 1.5 toint
|
||||
|
Reference in New Issue
Block a user