10 January 2010

Listing: fcall.pb


; fcall.pb
IncludeFile "..\base2.pb"
IncludeFile "..\labels.pb"
IncludeFile "..\symboltable.pb"


Procedure.s VarRef(*V.SVariable)
Select *V\RefKind
Case #Ref_Global
ProcedureReturn "[v_" + *V\Name + "]"
Default
Error("Unknown variable scope kind")
EndSelect
EndProcedure

; Return the asm for accessing the value of a variable
Procedure.s VarValue(Name.s)
Protected *V.SSymbol = LookupSymbol(Name)
If *V And *V\Kind = #SKind_Variable
ProcedureReturn VarRef(*V)
Else
Error("Undeclared variable: " + Name)
EndIf
EndProcedure

Procedure FunctionCall(Name.s)
*V.SFunction = LookupSymbolNoScopeResolve(Name)
If *V And *v\Kind = #SKind_Function
Emit("call " + *v\Ref)
Else
Error("Undeclared function: " + Name)
EndIf
EndProcedure

Procedure Value()
; value ::= <integer> | <variable> | <fcall()> | '(' <expression> ')'
Protected Name.s
If IsDigit(Look)
Emit("mov eax, " + GetInteger())
ElseIf IsAlpha(Look)
Name = GetName()
If Look = '('
Match('(')
FunctionCall(Name)
Match(')')
Else
Emit("mov eax, " + VarValue(Name))
EndIf
Else
Expected("value")
EndIf
EndProcedure

Procedure Expression()
; expression ::= <value>
Value()
EndProcedure

Procedure Assignment(Name.s)
; assignment ::= <name> = <expression>
MatchWhite('=')
Expression()
Emit2("mov ", VarValue(Name), "eax")
EndProcedure

Procedure VariableDeclaration()
; vardecl ::= var <name> as <type>
Protected Name.s
Protected TypeS.s, TypeI.i
Protected *V.SVariable

; Get name and type
Name = GetName()
If GetName() <> "as"
Expected("as")
EndIf
TypeS = GetName()

AddVariable(Name, TypeS, #Ref_Global, 0)
EndProcedure


Procedure Statement()
Protected N.s
N = GetName()
If Look = '('
Match('(')
FunctionCall(N)
Match(')')
Else
Select N
Case "var": VariableDeclaration()
Default: Assignment(N)
EndSelect
EndIf
EndProcedure

Procedure Program()
; program ::= { <assignment> }
EatWhiteNewlines()
While Look
Statement()
EatWhiteNewlines()
Wend
EndProcedure

Procedure GlobalAsmDefinition(ScopedName.s, *V.SVariable)
If *V\Kind = #SKind_Variable
If *V\RefKind = #Ref_Global
Emit("v_" + *v\Name + " dd 0")
EndIf
EndIf
EndProcedure

Procedure Footer()
Emit("push 0")
Emit("call _ExitProcess")
Emit("; Global variables: ")
EnumerateSymbols(@GlobalAsmDefinition())
EndProcedure

; Add a few functions to the symbol table so we can call them
*F.SFunction = AddFunction("MyFunc")
*F\Type = #TyLong

*F.SFunction = AddFunction("DoCoolStuff")
*F\Type = #TyLong


InitMulti()
Program()
Footer()
Input()

No comments: