From 65d7b615d2418e9664694d6a6e36b4a4e1429498 Mon Sep 17 00:00:00 2001 From: Jose Rodriguez Date: Tue, 21 Nov 2017 15:45:17 +0100 Subject: [PATCH] bugfix: static math functions All constant math functions where being evaluated to SIN (instead of SIN, COS, TAN, SQR...) --- symbols/builtin.py | 13 ++-- tests/functional/constrig.asm | 113 ++++++++++++++++++++++++++++++++++ tests/functional/constrig.bas | 13 ++++ zxbparser.py | 15 +++-- 4 files changed, 144 insertions(+), 10 deletions(-) create mode 100644 tests/functional/constrig.asm create mode 100644 tests/functional/constrig.bas diff --git a/symbols/builtin.py b/symbols/builtin.py index 83c2711af..9c2eaad1f 100644 --- a/symbols/builtin.py +++ b/symbols/builtin.py @@ -18,8 +18,8 @@ class SymbolBUILTIN(Symbol): - ''' Defines an BUILTIN function e.g. INKEY$(), RND() or LEN - ''' + """ Defines an BUILTIN function e.g. INKEY$(), RND() or LEN + """ def __init__(self, lineno, fname, type_=None, *operands): assert isinstance(lineno, int) assert type_ is None or isinstance(type_, SymbolTYPE) @@ -60,24 +60,25 @@ def operands(self, value): @property def size(self): - ''' sizeof(type) - ''' + """ sizeof(type) + """ if self.type_ is None: return 0 return self.type_.size @classmethod def make_node(cls, lineno, fname, func=None, type_=None, *operands): - ''' Creates a node for a unary operation. E.g. -x or LEN(a$) + """ Creates a node for a unary operation. E.g. -x or LEN(a$) Parameters: -func: function used on constant folding when possible -type_: the resulting type (by default, the same as the argument). For example, for LEN (str$), result type is 'u16' and arg type is 'string' - ''' + """ if func is not None and len(operands) == 1: # Try constant-folding if is_number(operands[0]) or is_string(operands[0]): # e.g. ABS(-5) + print(func.__name__) return SymbolNUMBER(func(operands[0].value), type_=type_, lineno=lineno) return cls(lineno, fname, type_, *operands) diff --git a/tests/functional/constrig.asm b/tests/functional/constrig.asm new file mode 100644 index 000000000..d1e9be1de --- /dev/null +++ b/tests/functional/constrig.asm @@ -0,0 +1,113 @@ + org 32768 +__START_PROGRAM: + di + push ix + push iy + exx + push hl + exx + ld hl, 0 + add hl, sp + ld (__CALL_BACK__), hl + ei + ld a, 07Fh + ld de, 099B3h + ld bc, 0F5DBh + ld hl, _a + call __STOREF + ld a, 080h + ld de, 0BBEFh + ld bc, 01EA0h + ld hl, _a + call __STOREF + ld a, 07Fh + ld de, 0C93Fh + ld bc, 064B0h + ld hl, _a + call __STOREF + ld a, 07Dh + ld de, 0244Dh + ld bc, 0B093h + ld hl, _a + call __STOREF + ld a, 081h + ld de, 03D3Ch + ld bc, 06791h + ld hl, _a + call __STOREF + ld a, 07Fh + ld de, 03915h + ld bc, 030D3h + ld hl, _a + call __STOREF + ld a, 081h + ld de, 05A20h + ld bc, 07589h + ld hl, _a + call __STOREF + ld a, 086h + ld de, 07604h + ld bc, 00939h + ld hl, _a + call __STOREF + ld a, 081h + ld de, 0776Fh + ld bc, 08B50h + ld hl, _a + call __STOREF + ld hl, 0 + ld b, h + ld c, l +__END_PROGRAM: + di + ld hl, (__CALL_BACK__) + ld sp, hl + exx + pop hl + exx + pop iy + pop ix + ei + ret +__CALL_BACK__: + DEFW 0 +#line 1 "storef.asm" + +__PISTOREF: ; Indect Stores a float (A, E, D, C, B) at location stored in memory, pointed by (IX + HL) + push de + ex de, hl ; DE <- HL + push ix + pop hl ; HL <- IX + add hl, de ; HL <- IX + HL + pop de + +__ISTOREF: ; Load address at hl, and stores A,E,D,C,B registers at that address. Modifies A' register + ex af, af' + ld a, (hl) + inc hl + ld h, (hl) + ld l, a ; HL = (HL) + ex af, af' + +__STOREF: ; Stores the given FP number in A EDCB at address HL + ld (hl), a + inc hl + ld (hl), e + inc hl + ld (hl), d + inc hl + ld (hl), c + inc hl + ld (hl), b + ret + +#line 63 "constrig.bas" + +ZXBASIC_USER_DATA: +_a: + DEFB 00, 00, 00, 00, 00 + ; Defines DATA END --> HEAP size is 0 +ZXBASIC_USER_DATA_END EQU ZXBASIC_MEM_HEAP + ; Defines USER DATA Length in bytes +ZXBASIC_USER_DATA_LEN EQU ZXBASIC_USER_DATA_END - ZXBASIC_USER_DATA + END diff --git a/tests/functional/constrig.bas b/tests/functional/constrig.bas new file mode 100644 index 000000000..d66e88a2f --- /dev/null +++ b/tests/functional/constrig.bas @@ -0,0 +1,13 @@ + +DIM a as Float + +a = SIN(3.5) +a = COS(3.5) +a = TAN(3.5) +a = ASN(0.1) +a = ACS(0.1) +a = ATN(0.3) +a = LN(3.5) +a = EXP(3.5) +a = SQR(3.5) + diff --git a/zxbparser.py b/zxbparser.py index d6b65882d..0b637ede7 100755 --- a/zxbparser.py +++ b/zxbparser.py @@ -194,8 +194,6 @@ def make_builtin(lineno, fname, operands, func=None, type_=None): operands = [] assert isinstance(operands, Symbol) or isinstance(operands, tuple) or isinstance(operands, list) # TODO: In the future, builtin functions will be implemented in an external library, like POINT or ATTR - # HINT: They are not yet, because Sinclair BASIC grammar allows not to use parenthesis e.g. SIN x = SIN(x) - # HINT: which requires syntactical changes in the parser __DEBUG__('Creating BUILTIN "{}"'.format(fname), 1) if not isinstance(operands, collections.Iterable): operands = [operands] @@ -3211,12 +3209,21 @@ def p_sgn(p): # ---------------------------------------- # Trigonometrics and LN, EXP, SQR # ---------------------------------------- -def p_expr_sin(p): +def p_expr_trig(p): """ bexpr : math_fn bexpr %prec UMINUS """ p[0] = make_builtin(p.lineno(1), p[1], make_typecast(TYPE.float_, p[2], p.lineno(1)), - lambda x: math.sin(x)) + {'SIN': math.sin, + 'COS': math.cos, + 'TAN': math.tan, + 'ASN': math.asin, + 'ACS': math.acos, + 'ATN': math.atan, + 'LN': lambda y: math.log(y, math.exp(1)), # LN(x) + 'EXP': math.exp, + 'SQR': math.sqrt + }[p[1]]) def p_math_fn(p):