mirror of
https://github.com/samsonjs/compiler.git
synced 2026-04-27 14:57:45 +00:00
[FIXED] handle unary plus and minary properly
This commit is contained in:
parent
f7e63cbe21
commit
55c047d0ef
2 changed files with 62 additions and 52 deletions
110
compiler.rb
110
compiler.rb
|
|
@ -50,6 +50,7 @@ class Compiler
|
||||||
if @look == '('
|
if @look == '('
|
||||||
# function call
|
# function call
|
||||||
match('(')
|
match('(')
|
||||||
|
# TODO arg list
|
||||||
match(')')
|
match(')')
|
||||||
x86_call(name)
|
x86_call(name)
|
||||||
else
|
else
|
||||||
|
|
@ -65,18 +66,32 @@ class Compiler
|
||||||
expression
|
expression
|
||||||
match(')')
|
match(')')
|
||||||
elsif alpha?(@look)
|
elsif alpha?(@look)
|
||||||
identifier
|
identifier # or call
|
||||||
elsif digit?(@look)
|
elsif digit?(@look)
|
||||||
x86_mov(:eax, get_num)
|
x86_mov(:eax, get_num)
|
||||||
else
|
else
|
||||||
expected(:'integer, identifier, or parenthesized expression')
|
expected(:'integer, identifier, function call, or parenthesized expression')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Parse a signed factor.
|
||||||
|
def signed_factor
|
||||||
|
unary_op = if @look == '-'
|
||||||
|
match('-')
|
||||||
|
:neg
|
||||||
|
elsif @look == '+'
|
||||||
|
match('+')
|
||||||
|
:pos
|
||||||
|
end
|
||||||
|
factor
|
||||||
|
x86_neg(:eax) if unary_op == :neg
|
||||||
|
end
|
||||||
|
|
||||||
# Parse and translate a single term (factor or mulop). Result is in
|
# Parse and translate a single term (factor or mulop). Result is in
|
||||||
# eax.
|
# eax.
|
||||||
def term
|
def term
|
||||||
factor # Result in eax.
|
signed_factor # Result in eax.
|
||||||
|
|
||||||
while mulop?
|
while mulop?
|
||||||
# Stash the 1st factor on the stack. This is expected by
|
# Stash the 1st factor on the stack. This is expected by
|
||||||
# multiply & divide. Because they leave their results in eax
|
# multiply & divide. Because they leave their results in eax
|
||||||
|
|
@ -97,13 +112,7 @@ class Compiler
|
||||||
# Parse and translate a general expression of terms. Result is
|
# Parse and translate a general expression of terms. Result is
|
||||||
# in eax.
|
# in eax.
|
||||||
def expression
|
def expression
|
||||||
if addop?
|
term # Result is in eax.
|
||||||
# Clear eax simulating a zero before unary plus and minus
|
|
||||||
# operations.
|
|
||||||
x86_xor(:eax, :eax)
|
|
||||||
else
|
|
||||||
term # Result is in eax.
|
|
||||||
end
|
|
||||||
|
|
||||||
while addop?
|
while addop?
|
||||||
# Stash the 1st term on the stack. This is expected by add &
|
# Stash the 1st term on the stack. This is expected by add &
|
||||||
|
|
@ -122,6 +131,47 @@ class Compiler
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Parse an addition operator and the 2nd term (b). The result is
|
||||||
|
# left in eax. The 1st term (a) is expected on the stack.
|
||||||
|
def add
|
||||||
|
match('+')
|
||||||
|
term # Result is in eax.
|
||||||
|
x86_add(:eax, '[esp]') # Add a to b.
|
||||||
|
end
|
||||||
|
|
||||||
|
# Parse a subtraction operator and the 2nd term (b). The result is
|
||||||
|
# left in eax. The 1st term (a) is expected on the stack.
|
||||||
|
def subtract
|
||||||
|
match('-')
|
||||||
|
term # Result, b, is in eax.
|
||||||
|
x86_neg(:eax) # Fake the subtraction. a - b == a + -b
|
||||||
|
x86_add(:eax, '[esp]') # Add a and -b.
|
||||||
|
end
|
||||||
|
|
||||||
|
# Parse an addition operator and the 2nd term (b). The result is
|
||||||
|
# left in eax. The 1st term (a) is expected on the stack.
|
||||||
|
def multiply
|
||||||
|
match('*')
|
||||||
|
signed_factor # Result is in eax.
|
||||||
|
x86_imul('dword [esp]') # Multiply a by b.
|
||||||
|
end
|
||||||
|
|
||||||
|
# Parse a division operator and the divisor (b). The result is
|
||||||
|
# left in eax. The dividend (a) is expected on the stack.
|
||||||
|
def divide
|
||||||
|
match('/')
|
||||||
|
signed_factor # Result is in eax.
|
||||||
|
x86_xchg(:eax, '[esp]') # Swap the divisor and dividend into
|
||||||
|
# the correct places.
|
||||||
|
|
||||||
|
# idiv uses edx:eax as the dividend so we need to ensure that edx
|
||||||
|
# is correctly sign-extended w.r.t. eax.
|
||||||
|
emit('cdq') # Sign-extend eax into edx (Convert Double to
|
||||||
|
# Quad).
|
||||||
|
x86_idiv('dword [esp]') # Divide a (eax) by b ([esp]).
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
# Parse an assignment statement. Value is in eax.
|
# Parse an assignment statement. Value is in eax.
|
||||||
def assignment
|
def assignment
|
||||||
name = get_name
|
name = get_name
|
||||||
|
|
@ -290,46 +340,6 @@ class Compiler
|
||||||
skip_whitespace
|
skip_whitespace
|
||||||
end
|
end
|
||||||
|
|
||||||
# Parse an addition operator and the 2nd term (b). The result is
|
|
||||||
# left in eax. The 1st term (a) is expected on the stack.
|
|
||||||
def add
|
|
||||||
match('+')
|
|
||||||
term # Result is in eax.
|
|
||||||
x86_add(:eax, '[esp]') # Add a to b.
|
|
||||||
end
|
|
||||||
|
|
||||||
# Parse a subtraction operator and the 2nd term (b). The result is
|
|
||||||
# left in eax. The 1st term (a) is expected on the stack.
|
|
||||||
def subtract
|
|
||||||
match('-')
|
|
||||||
term # Result, b, is in eax.
|
|
||||||
x86_neg(:eax) # Fake the subtraction. a - b == a + -b
|
|
||||||
x86_add(:eax, '[esp]') # Add a and -b.
|
|
||||||
end
|
|
||||||
|
|
||||||
# Parse an addition operator and the 2nd term (b). The result is
|
|
||||||
# left in eax. The 1st term (a) is expected on the stack.
|
|
||||||
def multiply
|
|
||||||
match('*')
|
|
||||||
factor # Result is in eax.
|
|
||||||
x86_imul('dword [esp]') # Multiply a by b.
|
|
||||||
end
|
|
||||||
|
|
||||||
# Parse a division operator and the divisor (b). The result is
|
|
||||||
# left in eax. The dividend (a) is expected on the stack.
|
|
||||||
def divide
|
|
||||||
match('/')
|
|
||||||
factor # Result is in eax.
|
|
||||||
x86_xchg(:eax, '[esp]') # Swap the divisor and dividend into
|
|
||||||
# the correct places.
|
|
||||||
|
|
||||||
# idiv uses edx:eax as the dividend so we need to ensure that edx
|
|
||||||
# is correctly sign-extended w.r.t. eax.
|
|
||||||
emit('cdq') # Sign-extend eax into edx (Convert Double to
|
|
||||||
# Quad).
|
|
||||||
x86_idiv('dword [esp]') # Divide a (eax) by b ([esp]).
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
############
|
############
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ a=9
|
||||||
aa=10
|
aa=10
|
||||||
somethinglong=65536
|
somethinglong=65536
|
||||||
x=5*(3-5)
|
x=5*(3-5)
|
||||||
c=a-1
|
c=1--a
|
||||||
g=-1
|
g=1*-1
|
||||||
h=x*2+2
|
h=x*2+2
|
||||||
j=h-27/9
|
j=h-27/9
|
||||||
k=j-8/2
|
k=j-8/2
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue