10 January 2010

Listing: fcallparm.pb


; fcallparm.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

Declare Expression()
Procedure FunctionParameters(*F.SFunction)
Protected ParamStackSize = *F\ParamCount*4 ; Note, it's 4 because we use longs. Doubles and quads would be 8!
Protected I
Emit2("sub ", "esp", Str(ParamStackSize)) ; Make room on the stack for the parameters
For I = 0 To *F\ParamCount-1
Expression()
Emit("mov [esp+" + Str(I*4) + "], eax")
If I <> *F\ParamCount-1 ; If the current parameter is NOT the last one
MatchWhite(',') ; Get a comma and whitespace to prepare for the next parameter
EndIf
Next
EndProcedure

Procedure FunctionCall(Name.s)
Protected *F.SFunction = LookupSymbolNoScopeResolve(Name)
If *F And *F\Kind = #SKind_Function
If *F\ParamCount > 0
FunctionParameters(*F)
EndIf
Emit("call " + *F\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("")
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\ParamCount = 1
*F\ParamTypes[0] = #TyLong

*F.SFunction = AddFunction("DoCoolStuff")
*F\Type = #TyLong
*f\ParamCount = 3
*f\ParamTypes[0] = #TyLong
*f\ParamTypes[1] = #TyLong
*f\ParamTypes[2] = #TyLong


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

7 comments:

Unknown said...

I had almost given up checking back here.
Thanks for continuing.
Hope to see more.

Unknown said...

I know you said that you were not going to post all of the code. You wanted people to go through the tutorial to learn it themselves....
But, please reconsider.

You can tell me that Mount Everest is the tallest mountain; I do not need to climb it to understand that.

I have been reading your articles. but that is all. It would be nice to be able to download the current code as a zip and to then play with it.
Additionally it would be great to have the series in pdf format.

Do I ask for too much ;-)

Cheers.

Invincible Cow said...

I am posting all of the code.
That's what the listings are for. You're supposed to copy and paste them into the PB IDE and save them for later.

Unknown said...

I was just being extra lazy I guess.
I mean after all, cut AND paste. :-p
That's like 2 mouse clicks.
I was hoping to get it down to 1 mouse click. ;-)

But, seriously, I enjoy the series very much.

Melitene said...

I must be blind, but I've looked through all of the posts and I can't find the MatchWhite()-procedure anywhere! Could you post it or give a hint on where to find it?

Melitene said...

Ah, never mind, found it now. I was indeed blind!

Thank you very much for the series, it has been interesting. I really hope you keep it up and extend it.

Peyman said...

Thanks very interesting,
this is possible for you or one body here to post a zip file because i cant read and write english very well and i every time try to copy & Paste your code i fail. please if possible publish a zip version.