TriOS-alt/zubehör/sphinx/spinx100225-ori/sphinx2/eval.spn

216 lines
7.2 KiB
Plaintext

obj
kw : "kwdefs"
token : "tokenrdr"
bt : "bintree"
st : "symbols"
dat
pass byte 0
insideDAT byte 0
ignoreUndefined byte 0
evalSuccess byte 0
pGlobalLabel word 0
pub set_Pass( p )
pass := p
pub get_Pass
return pass
pub EnteringDat
insideDAT~~
pub LeavingDat
insideDAT~
pub Succeeded
return evalSuccess
pub TryToEvaluateExpression( _pGlobalLabel )
{{
}}
pGlobalLabel := _pGlobalLabel
ignoreUndefined~~
evalSuccess~~
return Evaluate( 13 )
pub EvaluateExpression( _pGlobalLabel )
pGlobalLabel := _pGlobalLabel
ignoreUndefined~
evalSuccess~~
return Evaluate( 13 )
pri Evaluate( rbp ) | prec, lbp, t
prec := token.GetPrecedence
if token.AdvanceIf( kw#kAT )
result := EvaluateSymbol( true )
elseif (token.IsUnaryOp and not token.IsPostfixOp) or token.Type == kw#kMINUS
t := token.Type
token.Advance
result := EvaluateUnary( t, prec )
elseif token.AdvanceIf( kw#kLPAREN )
result := Evaluate( 13 )
token.Eat( kw#kRPAREN )
elseif token.IsIntLiteral or token.IsFloatLiteral
result := token.Value
token.Advance
elseif token.IsReg
result := $1f0 + token.GetReg
token.Advance
else
result := EvaluateSymbol( false )
repeat
lbp := token.GetPrecedence
if rbp =< lbp
quit
t := token.Type
token.Advance
result := EvaluateBinary( t, result, Evaluate( lbp ) )
pri EvaluateSymbol( takeAddress ) | p, t, pObj, cogx4, pLocalLabels
{{
CON symbols evaluate as their defined values, as do OBJ#constants.
DAT symbols evaluate differently depending on context.
}}
if byte[token.Text] == ":" ' local label?
ifnot pGlobalLabel
abort string("Unknown local label(1)")
p := pGlobalLabel ' Search local label list for current token.
repeat
ifnot p := bt.PeekW( p + 6 ) ' p points to string part of local label
if ignoreUndefined
evalSuccess~
token.Advance
return -1 ' dummy value
abort string("Unknown local label(2)")
if strcomp( p, token.Text )
quit
p += strsize(p) + 1 ' Increment p past string part to data part
' On exit, we've found the local label.
p += strsize(p) + 1 ' Increment p past string part to data part
else
p := st.SymbolLookup( token.Text )
ifnot p
if ignoreUndefined
evalSuccess~
token.Advance
return -1
abort string("Unknown symbol")
t := byte[p]
if t == st#kINT_CON_SYMBOL or t == st#kFLOAT_CON_SYMBOL or t == st#kBUILTIN_INT_SYMBOL or t == st#kBUILTIN_FLOAT_SYMBOL
' TODO: should handle floats differently
if takeAddress
abort string("Can't take address of CON symbol")
token.Advance
return bt.PeekL( p+1 )
if t == st#kUNDEFINED_CON_SYMBOL
if ignoreUndefined
evalSuccess~
token.Advance
return -1 ' dummy value
abort string("Undefined CON symbol")
if t == st#kOBJ_SYMBOL
if takeAddress
abort string("Can't take address of OBJ symbol")
token.Advance
p := bt.PeekW( p+1 )
pObj := bt.PeekW( p + strsize(p) + 2 )
token.Eat( kw#kOCTOTHORP )
ifnot p := bt.FindInTable( token.Text, pObj )
abort string("CON symbol unknown in sub-object")
't := byte[p] -- at this point, t should be either kINT_CON_SYMBOL or kFLOAT_CON_SYMBOL
' TODO: should handle floats differently
token.Advance
return bt.PeekL( p+1 )
if t == st#kDAT_SYMBOL
if pass == 1
if ignoreUndefined
evalSuccess~
token.Advance
return -1 ' dummy value
if takeAddress
abort string("Can't take address of DAT symbol in pass 1")
if not insideDAT or takeAddress
token.Advance
return bt.PeekW( p+2 )
cogx4 := bt.PeekW( p+4 )
if cogx4 & 3
abort string("Address is not long")
token.Advance
return cogx4 >> 2
abort string("Invalid symbol in constant expression")
pri EvaluateUnary( t, prec )
{{
}}
result := Evaluate( prec )
case t & $ff
$ed: -result
$e7: !result
$ff: not result
$f3: |<result
$f1: >|result
$f8: ^^result
$e9: ||result
other: abort string("Syntax error in constant expression(1)")
pri EvaluateBinary( t, a, b )
case t & $ff
$ec: return a + b
$ed: return a - b
$f4: return a * b
$f6: return a / b
$f5: return a ** b
$f7: return a // b
$e0: return a -> b
$e1: return a <- b
$e2: return a >> b
$e3: return a << b
$ee: return a ~> b
$ef: return a >< b
$e8: return a & b
$ea: return a | b
$eb: return a ^ b
$e4: return a #> b
$e5: return a <# b
$f9: return a < b
$fa: return a > b
$fc: return a == b
$fb: return a <> b
$fd: return a =< b
$fe: return a => b
$f0: return a and b
$f2: return a or b
other: abort string("Syntax error in constant expression(2)")
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| TERMS OF USE: MIT License |
+------------------------------------------------------------------------------------------------------------------------------+
|Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation |
|files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, |
|modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software|
|is furnished to do so, subject to the following conditions: |
| |
|The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.|
| |
|THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
|WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
|ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
+------------------------------------------------------------------------------------------------------------------------------+
}}