DarkMachine Engine's Compiler parses *.dm/*.dmc source code and generates PCode instructions *.dmo that are executed by the Virtual Machine. I selected this method over interpreting for speed and security.
I started with Mark Sibly's Compiler Code because it had a excellent way of parsing expressions and tokenizing BASIC statements, keywords, etc and output instructions. With some research and reading on Assembler, I was armed with enough info to pursue development of DarkMachine. The best way to get a feel for the internal workings of the compiler is to examine the dmcvm_Compiler.bb.
Extremely High Level Overview
The Compiler consists of 8 functions that work together recursively to generate Pcode:
1. dmcvm_CompilerLoad()
2. dmcvm_CompilerTokenGet()
2. dmcvm_CompilerParseStatement()
3. dmcvm_CompilerParseExpession()
4. dmcvm_CompilerParseTerm()
5. dmcvm_CompilerParseFact()
6. dmcvm_CompilerParseLeaf()
7. dmcvm_CompilerParseArguments()The dmcvm_CompilerLoad() loads *.dmc file line by line. The dmcvm_TokenGet() parses the line by one character at a time returning a BSCVM_TOKEN that represents a Keyword, Value, Array, Variable, or CALL to the function that called it, usually the dmcvm_CompilerStatement().
The dmcvm_CompilerStatement() is reponsible for generating PCode for Keyword Constructs and Assignments to Variable/Array from the BSCVM_TOKENs returned by dmcvm_TokenGet().
dmcvm_CompilerParseExpression() is reponsible generating PCode for Conditions like Equal_to, Greater_than, etc.
dmcvm_CompilerParseTerm() and dmcvm_CompilerParseFact() are responsible for generating PCode for math operations.
dmcvm_CompilerParseLeaf()is reponsible for generating PCode for Keyword Constructs and Assignments from Variable/Array and Calls.
dmcvm_CompilerParseArguments() generates PCode for generating PCode for Call Parameters.
BlitzBasic3D --> OpCode Conversion
Select...Case
Select a
Case 1
a=2
Case 2, 0
a=1
Default
a=0
EndSelect;Select a
mov eax,[a]
mov ebx, eax;Case 1
label_2
mov eax,1
cEQ eax, ebx
jz label_3;a=2
mov eax,2
mov [a], eax
jmp label_1;Case 2
label_3
mov eax,2
push eax
mov eax,0
pop ecx
or eax, ecx
cEQ eax, ebx
jz label_4;a=1
mov eax,1
mov [a], eax
jmp label_1;Default
label_4;a=0
mov eax,0
mov [a], eax
jmp label_1;EndSelect
label_5
label_1end
For...Next
For a = 1 To 10 Step 2
b=1
Next;For a = 1 To 10 Step 2
mov eax,1
mov [a], eax
label_2
mov eax, [a]
push eax
mov eax,10
pop ecx
cLT eax, ecx
jz label_1;b=1
mov eax,1
mov [b], eax;Next
mov eax, [a]
add eax, 2.0
mov [a], eax
jmp label_2
label_1Repeat...Until
Repeat
a=a-1
Until a=0;Repeat
label_2;a=a-1
mov eax,[a]
push eax
mov eax,1
pop ecx
sub eax,ecx
mov [a], eax;Until a=0
mov eax,[a]
push eax
mov eax,0
pop ecx
cEQ ecx,eax
jz label_2
label_1
While...Wend
While a<10
a=a+1
WendWhile a<10
label_2
mov eax,[a]
push eax
mov eax,10
pop ecx
cLT ecx,eax
jz label_1;a=a+1
mov eax,[a]
push eax
mov eax,1
pop ecx
add eax,ecx
mov [a], eax;Wend
jmp label_2
label_1