Code archives/Algorithms/ultra lite script language

This code has been declared by its author to be Public Domain code.

Download source code

ultra lite script language by ziggy2007
This is a simple ultra lite script language written in BlitzMax. It is not complete and has a very small number of features, but I did in a couple of evenings just for fun and I think some one can find it usefull.

This is the current list of features:
Variable declaration and assignation
Integration of external BMX functions to the script
While blocks
If / Else / EndIf blocks
Single line comments

This is a sample script:
'Sample silly program
print "Program started at time code " ++ millisecs()
dim A = ""
while not(a = "12345678")
	a = input("Enter password to proceed> ")
wend
print "Welcome to the restricted area."


Current sentences are: Dim, Print, While, Wend, If, Else, EndIf.

the only finished area is the expression evaluator, wich currently suports:
+
-
*
/
^
AND
OR
++ (string concatenation)
== (string comparison)
= (numeric comparison)
>> (string greater )
<< (string smaller)
>
<
=
>=
<=
( and )
function calls

All the variables in the script language can store numeric values or string values, that's why there are string speciffic operators. That is "1" = "1.000" will return true and "1" == "1.000" will return false. In the same way you can 1 = 1.0 will return true, 1 = "1.000" will also return true, but 1 == "1.000" will return false.

This is a list of available functions:
Sin
Tan
ASin
ACos
ATan
SinH
CosH
TanH
ATan2
Ceil
Int (with optional round second parameter true or false, by default it is true)
Sqr
Log
Log10
Floor
Exp
Chr
Asc
Left
Right
Mid
UCase
Input
Not
Rand
SeedRnd

This is a very stupid sampel script test.
Save it as scripttest.bs in the program folder or it will have no script to run!
'**************************************************************************************************
' This program was written with BLIde (http://www.blide.org)
' Application:
' Author:
' License:
'**************************************************************************************************

Framework brl.StandardIO
Import pub.Win32
Import brl.Retro
Import brl.system
SuperStrict
'#Region Initializations:
Private
Const _Version:String = "BScript 0.1"
Public
Local Compiler:TCompiler = New TCompiler
'#End Region

'#Region Load the script source code and compile it
Local F:TTextStream = LoadStreamText("scripttest.bs") 
If f = Null Then
	Notify("Missing file scripttest.bs Get this file from here: http://www.blitzmax.com/codearcs/codearcs.php?code=2103#comments") 
	End
EndIf
Local code:String[] 
Print "COMPILING..."
code = compiler.Compile(F) 
'#End Region

'#Region: Execution of the compiled script:

'First of all, we check the script was properly compiled:
If compiler.Error_Line <> - 1 Then
	Print "   Compile error"
	Print "   Description:" + compiler.Error_Description
	Print "   At line number:" + compiler.Error_Line
	Print "   Where code is:" + MTrim(compiler.error_sourcecode) 
	Print "COMPILATION CANCELED."
	End
End If

'In this sample, we show compilation results information:
Print "   Source code " + compiler.CompiledLines + " lines of code."
Print "   Generated VMA code: " + code.length + " lines of code"
Print "   Debug info present: " + compiler.ProduceDebug
Print "COMPILED"
'We show the user the compiled source code (just for this sample):
Input "Press enter to view the VMA source code."
Print "."
Print "."
Print "."
Local ex:TExecuter
ex = New TExecuter

'In case there's a compilation error or empty script, there's nothing to show:
If code = Null Then
	Print "Compilation error"
	End
EndIf
'Otherwise we show the source code:
Local StrOut:String
For Local i:Int = 0 To code.Length - 1
	Print i + " : " + code[i] 
	StrOut = StrOut + code[i] + Chr(13) + Chr(10) 
Next
'We save the compiled source code, just to show how easy it is once it is placed all together:
SaveText(strout, "compiled.vma") 
'#End Region

'#Region Finally, the Script is executed:
Input "Press ENTER to run the program"
ex.Execute(code) 
End
'#End Region

'summary:This class generates VMA compiled output for arithmetic expressions
Type TCompEvaluator
	Field _IntCount:Int
	Field _IntCode:TList
	Field TargetScope:TScope
	Const AndStr:String = Chr(1) 
	Const OrStr:String = Chr(2) 
	Field ErrorDescription:String
	Method CompEvaluate:String[] (Expr:String, LastEx:String Var, IsLiteral:Int Var) 
		Try
			Self._BeginCompExpr() 
			expr = ReplaceB(expr, " AND ", AndStr, True) 
			expr = ReplaceB(expr, ")AND ", ")" + AndStr, True) 
			expr = ReplaceB(expr, " AND(", AndStr + "(", True) 
			expr = ReplaceB(expr, "]AND ", "]" + AndStr, True) 
			expr = ReplaceB(expr, " AND[", AndStr + "[", True) 
			expr = ReplaceB(expr, " OR ", OrStr, True) 
			expr = ReplaceB(expr, ")OR ", ")" + OrStr, True) 
			expr = ReplaceB(expr, " OR(", OrStr + "(", True) 
			expr = ReplaceB(expr, "]OR ", "]" + OrStr, True) 
			expr = ReplaceB(expr, " OR[", OrStr + "[", True) 
			expr = ReplaceB(Expr, " ", "", False, True) 
			LastEx = _compevaluate(Expr) 
			If GetSufix(LastEx, False) = "N" Then
				Local leftl:Int = 0, forcenum:Int = 0
				LastEx = GetLeftId(LastEx, LastEx.Length, Leftl, forcenum) 
				IsLiteral = True
			End If
	
			Local SR:String[_intcode.Count()] 
			For Local i:Int = 0 To sr.Length - 1
				sr[i] = String(_intcode.ValueAtIndex(i)) 
			Next
			Return sr
		Catch Ex:String
			Self.ErrorDescription = "Error in expression:" + Ex
			Return Null
		End Try
	End Method
	Method _CompEvaluate:String(Expr:String) 
		Local OpIndex:Int
		Local LeftL:Int = 0, RightL:Int = 0
		Local SubExIndex:Int = InstrB(Expr, "(") 
		Local FNL:Int = 0
		Local FNR:Int = 0
		While SubExIndex
			Local subS:String
			subS = Mid(Expr, InstrB(Expr, "(") + 1) 
			Local ParamCount:Int = 1
			Local found:Int = False
			Local lastindex:Int = 0
			For Local i:Int = 0 To subs.Length
				If Mid(subs, i, 1) = "(" Then ParamCount:+1
				If Mid(subs, i, 1) = ")" Then
					paramcount:-1
					If paramcount = 0 Then
						found = True
						LastIndex = i
						Exit
					EndIf
				EndIf
			Next
			If found = False
				Return "!Err"
			Else
				Local IsFunction:Int = False
				If subexindex >= 1 Then
					Local Chk:String = Mid(Expr, subexindex - 1, 1) 
					If IsOperator(CHK) = False Then
						isfunction = True
						Local chars:Int = 0
						Local FunctionId:String = GetLeftId(Expr, subexindex - 1, chars, FNL) 
						Expr = Left(Expr, InstrB(Expr, "(") - chars - 1) + CallFunction(functionid, Left(subs, lastindex - 1)) + Mid(expr, subexindex + lastindex + 1) 
					End If
				EndIf
				If isfunction = False Then
					Expr = Left(Expr, InstrB(Expr, "(") - 1) + _compEvaluate(Left(subs, lastindex - 1)) + Mid(expr, subexindex + lastindex + 1) 
				EndIf
			End If
			SubExIndex:Int = InstrB(Expr, "(") 
		Wend
		'#Region STC	->String concatenation
		OpIndex = InstrB(Expr, "++") 
		While OpIndex
			Local LI:String = GetLeftId(Expr, Opindex - 1, leftL, FNL) 
			Local RI:String = GetRightId(Expr, Opindex + 2, RightL, FNR) 
			Self.CompOutput("STC" + GetSufix(LI, FNL) + GetSufix(RI, FNR)) 
			Local ExprS:String = GetExprName() 
			Self.CompOutput(ExprS) 
			Self.CompOutput(LI) 
			Self.CompOutput(RI) 
			Expr = Left(Expr, Opindex - LeftL - 1) + ExprS + Mid(Expr, Opindex + RightL + 1 + 1) 
			OpIndex = InstrB(Expr, "++") 
			checkvariables(LI, FNL, RI, FNR) 
		Wend
		'#End Region
		'#Region EXP
		OpIndex = InstrB(Expr, "^") 
		While OpIndex
			Local LI:String = GetLeftId(Expr, Opindex - 1, leftL, FNL) 
			Local RI:String = GetRightId(Expr, Opindex + 1, RightL, FNR) 
			Self.CompOutput("EXP" + GetSufix(LI, FNL) + GetSufix(RI, FNR)) 
			Local ExprS:String = GetExprName() 
			Self.CompOutput(ExprS) 
			Self.CompOutput(LI) 
			Self.CompOutput(RI) 
			Expr = Left(Expr, Opindex - LeftL - 1) + ExprS + Mid(Expr, Opindex + RightL + 1) 
			OpIndex = InstrB(Expr, "^") 
			checkvariables(LI, FNL, RI, FNR) 

		Wend
		'#End Region
		
		'#Region DIV
		OpIndex = InstrB(Expr, "/") 
		While OpIndex
			Local LI:String = GetLeftId(Expr, Opindex - 1, leftL, FNL) 
			Local RI:String = GetRightId(Expr, Opindex + 1, RightL, FNR) 
			Self.CompOutput("DIV" + GetSufix(LI, FNL) + GetSufix(RI, FNR)) 
			Local ExprS:String = GetExprName() 
			Self.CompOutput(ExprS) 
			Self.CompOutput(LI) 
			Self.CompOutput(RI) 
			Expr = Left(Expr, Opindex - LeftL - 1) + ExprS + Mid(Expr, Opindex + RightL + 1) 
			OpIndex = InstrB(Expr, "/") 
			checkvariables(LI, FNL, RI, FNR) 
		Wend
		'#End Region


				
		'#Region MUL
		OpIndex = InstrB(Expr, "*") 
		While OpIndex
			Local LI:String = GetLeftId(Expr, Opindex - 1, leftL, FNL) 
			Local RI:String = GetRightId(Expr, Opindex + 1, RightL, FNR) 
			Self.CompOutput("MUL" + GetSufix(LI, FNL) + GetSufix(RI, FNR)) 
			Local ExprS:String = GetExprName() 
			Self.CompOutput(ExprS) 
			Self.CompOutput(LI) 
			Self.CompOutput(RI) 
			Expr = Left(Expr, Opindex - LeftL - 1) + ExprS + Mid(Expr, Opindex + RightL + 1) 
			OpIndex = InstrB(Expr, "*") 
			checkvariables(LI, FNL, RI, FNR) 

		Wend
		'#End Region

		
		'#Region SUB
		OpIndex = InstrB(Expr, "-") 
		While OpIndex
			Local LI:String = GetLeftId(Expr, Opindex - 1, leftL, FNL) 
			Local RI:String = GetRightId(Expr, Opindex + 1, RightL, FNR) 
			Self.CompOutput("SUB" + GetSufix(LI, FNL) + GetSufix(RI, FNR)) 
			Local ExprS:String = GetExprName() 
			Self.CompOutput(ExprS) 
			Self.CompOutput(LI) 
			Self.CompOutput(RI) 
			Expr = Left(Expr, Opindex - LeftL - 1) + ExprS + Mid(Expr, Opindex + RightL + 1) 
			OpIndex = InstrB(Expr, "-") 
			checkvariables(LI, FNL, RI, FNR) 
		Wend
		'#End Region
			
		'#Region +
		OpIndex = InstrB(Expr, "+") 
		While OpIndex
			Local LI:String = GetLeftId(Expr, Opindex - 1, leftL, FNL) 
			Local RI:String = GetRightId(Expr, Opindex + 1, RightL, FNR) 
			Self.CompOutput("SUM" + GetSufix(LI, FNL) + GetSufix(RI, FNR)) 
			Local ExprS:String = GetExprName() 
			Self.CompOutput(ExprS) 
			Self.CompOutput(LI) 
			Self.CompOutput(RI) 
			Expr = Left(Expr, Opindex - LeftL - 1) + ExprS + Mid(Expr, Opindex + RightL + 1) 
			OpIndex = InstrB(Expr, "+") 
			checkvariables(LI, FNL, RI, FNR) 
		Wend
		'#End Region
		
		'#Region EQS	->String comparison
		OpIndex = InstrB(Expr, "==") 
		While OpIndex
			Local LI:String = GetLeftId(Expr, Opindex - 1, leftL, FNL) 
			Local RI:String = GetRightId(Expr, Opindex + 2, RightL, FNR) 
			Self.CompOutput("EQS" + GetSufix(LI, FNL) + GetSufix(RI, FNR)) 
			Local ExprS:String = GetExprName() 
			Self.CompOutput(ExprS) 
			Self.CompOutput(LI) 
			Self.CompOutput(RI) 
			Expr = Left(Expr, Opindex - LeftL - 1) + ExprS + Mid(Expr, Opindex + RightL + 1 + 1) 
			OpIndex = InstrB(Expr, "==") 
			checkvariables(LI, FNL, RI, FNR) 
		Wend
		'#End Region
		
		'#Region GRS ->String comparison
		OpIndex = InstrB(Expr, ">>") 
		While OpIndex
			Local LI:String = GetLeftId(Expr, Opindex - 1, leftL, FNL) 
			Local RI:String = GetRightId(Expr, Opindex + 2, RightL, FNR) 
			Self.CompOutput("GRS" + GetSufix(LI, FNL) + GetSufix(RI, FNR)) 
			Local ExprS:String = GetExprName() 
			Self.CompOutput(ExprS) 
			Self.CompOutput(LI) 
			Self.CompOutput(RI) 
			Expr = Left(Expr, Opindex - LeftL - 1) + ExprS + Mid(Expr, Opindex + RightL + 1 + 1) 
			OpIndex = InstrB(Expr, ">>") 
			checkvariables(LI, FNL, RI, FNR) 
		Wend
		'#End Region
		
		'#Region SMS ->String comparison
		OpIndex = InstrB(Expr, "<<") 
		While OpIndex
			Local LI:String = GetLeftId(Expr, Opindex - 1, leftL, FNL) 
			Local RI:String = GetRightId(Expr, Opindex + 2, RightL, FNR) 
			Self.CompOutput("SMS" + GetSufix(LI, FNL) + GetSufix(RI, FNR)) 
			Local ExprS:String = GetExprName() 
			Self.CompOutput(ExprS) 
			Self.CompOutput(LI) 
			Self.CompOutput(RI) 
			Expr = Left(Expr, Opindex - LeftL - 1) + ExprS + Mid(Expr, Opindex + RightL + 1 + 1) 
			OpIndex = InstrB(Expr, "<<") 
			checkvariables(LI, FNL, RI, FNR) 
		Wend
		'#End Region
		
		'#Region GRE ->String comparison
		OpIndex = InstrB(Expr, ">=") 
		While OpIndex
			Local LI:String = GetLeftId(Expr, Opindex - 1, leftL, FNL) 
			Local RI:String = GetRightId(Expr, Opindex + 2, RightL, FNR) 
			Self.CompOutput("GRE" + GetSufix(LI, FNL) + GetSufix(RI, FNR)) 
			Local ExprS:String = GetExprName() 
			Self.CompOutput(ExprS) 
			Self.CompOutput(LI) 
			Self.CompOutput(RI) 
			Expr = Left(Expr, Opindex - LeftL - 1) + ExprS + Mid(Expr, Opindex + RightL + 1 + 1) 
			OpIndex = InstrB(Expr, ">=") 
			checkvariables(LI, FNL, RI, FNR) 
		Wend
		OpIndex = InstrB(Expr, "=>") 
		While OpIndex
			Local LI:String = GetLeftId(Expr, Opindex - 1, leftL, FNL) 
			Local RI:String = GetRightId(Expr, Opindex + 2, RightL, FNR) 
			Self.CompOutput("GRE" + GetSufix(LI, FNL) + GetSufix(RI, FNR)) 
			Local ExprS:String = GetExprName() 
			Self.CompOutput(ExprS) 
			Self.CompOutput(LI) 
			Self.CompOutput(RI) 
			Expr = Left(Expr, Opindex - LeftL - 1) + ExprS + Mid(Expr, Opindex + RightL + 1 + 1) 
			OpIndex = InstrB(Expr, "=>") 
			checkvariables(LI, FNL, RI, FNR) 
		Wend

		'#End Region

		'#Region SME ->String comparison
		OpIndex = InstrB(Expr, "<=") 
		While OpIndex
			Local LI:String = GetLeftId(Expr, Opindex - 1, leftL, FNL) 
			Local RI:String = GetRightId(Expr, Opindex + 2, RightL, FNR) 
			Self.CompOutput("SME" + GetSufix(LI, FNL) + GetSufix(RI, FNR)) 
			Local ExprS:String = GetExprName() 
			Self.CompOutput(ExprS) 
			Self.CompOutput(LI) 
			Self.CompOutput(RI) 
			Expr = Left(Expr, Opindex - LeftL - 1) + ExprS + Mid(Expr, Opindex + RightL + 1 + 1) 
			OpIndex = InstrB(Expr, "<=") 
			checkvariables(LI, FNL, RI, FNR) 
		Wend
		OpIndex = InstrB(Expr, "=<") 
		While OpIndex
			Local LI:String = GetLeftId(Expr, Opindex - 1, leftL, FNL) 
			Local RI:String = GetRightId(Expr, Opindex + 2, RightL, FNR) 
			Self.CompOutput("SME" + GetSufix(LI, FNL) + GetSufix(RI, FNR)) 
			Local ExprS:String = GetExprName() 
			Self.CompOutput(ExprS) 
			Self.CompOutput(LI) 
			Self.CompOutput(RI) 
			Expr = Left(Expr, Opindex - LeftL - 1) + ExprS + Mid(Expr, Opindex + RightL + 1 + 1) 
			OpIndex = InstrB(Expr, "=<") 
			checkvariables(LI, FNL, RI, FNR) 
		Wend
		'#End Region
		
		'#Region EQU =
		OpIndex = InstrB(Expr, "=") 
		While OpIndex
			Local LI:String = GetLeftId(Expr, Opindex - 1, leftL, FNL) 
			Local RI:String = GetRightId(Expr, Opindex + 1, RightL, FNR) 
			Self.CompOutput("EQU" + GetSufix(LI, FNL) + GetSufix(RI, FNR)) 
			Local ExprS:String = GetExprName() 
			Self.CompOutput(ExprS) 
			Self.CompOutput(LI) 
			Self.CompOutput(RI) 
			Expr = Left(Expr, Opindex - LeftL - 1) + ExprS + Mid(Expr, Opindex + RightL + 1) 
			OpIndex = InstrB(Expr, "=") 
			checkvariables(LI, FNL, RI, FNR) 
		Wend
		'#End Region

		'#Region GR
		OpIndex = InstrB(Expr, ">") 
		While OpIndex
			Local LI:String = GetLeftId(Expr, Opindex - 1, leftL, FNL) 
			Local RI:String = GetRightId(Expr, Opindex + 1, RightL, FNR) 
			Self.CompOutput("GR" + GetSufix(LI, FNL) + GetSufix(RI, FNR)) 
			Local ExprS:String = GetExprName() 
			Self.CompOutput(ExprS) 
			Self.CompOutput(LI) 
			Self.CompOutput(RI) 
			Expr = Left(Expr, Opindex - LeftL - 1) + ExprS + Mid(Expr, Opindex + RightL + 1) 
			OpIndex = InstrB(Expr, ">") 
			checkvariables(LI, FNL, RI, FNR) 
		Wend
		'#End Region

		'#Region SM
		OpIndex = InstrB(Expr, "<") 
		While OpIndex
			Local LI:String = GetLeftId(Expr, Opindex - 1, leftL, FNL) 
			Local RI:String = GetRightId(Expr, Opindex + 1, RightL, FNR) 
			Self.CompOutput("SM" + GetSufix(LI, FNL) + GetSufix(RI, FNR)) 
			Local ExprS:String = GetExprName() 
			Self.CompOutput(ExprS) 
			Self.CompOutput(LI) 
			Self.CompOutput(RI) 
			Expr = Left(Expr, Opindex - LeftL - 1) + ExprS + Mid(Expr, Opindex + RightL + 1) 
			OpIndex = InstrB(Expr, "<") 
			checkvariables(LI, FNL, RI, FNR) 
		Wend
		'#End Region

					
		'#Region AND
		OpIndex = InstrB(Expr, andstr) 
		While OpIndex
			Local LI:String = GetLeftId(Expr, Opindex - 1, leftL, FNL) 
			Local RI:String = GetRightId(Expr, Opindex + 1, RightL, FNR) 
			Self.CompOutput("AND" + GetSufix(LI, FNL) + GetSufix(RI, FNR)) 
			Local ExprS:String = GetExprName() 
			Self.CompOutput(ExprS) 
			Self.CompOutput(LI) 
			Self.CompOutput(RI) 
			Expr = Left(Expr, Opindex - LeftL - 1) + ExprS + Mid(Expr, Opindex + RightL + 1) 
			OpIndex = InstrB(Expr, andstr) 
			checkvariables(LI, FNL, RI, FNR) 
		Wend
		'#End Region
		
		'#Region OR
		OpIndex = InstrB(Expr, orstr) 
		While OpIndex
			Local LI:String = GetLeftId(Expr, Opindex - 1, leftL, FNL) 
			Local RI:String = GetRightId(Expr, Opindex + 1, RightL, FNR) 
			Self.CompOutput("OR" + GetSufix(LI, FNL) + GetSufix(RI, FNR)) 
			Local ExprS:String = GetExprName() 
			Self.CompOutput(ExprS) 
			Self.CompOutput(LI) 
			Self.CompOutput(RI) 
			Expr = Left(Expr, Opindex - LeftL - 1) + ExprS + Mid(Expr, Opindex + RightL + 1) 
			OpIndex = InstrB(Expr, orstr) 
			checkvariables(LI, FNL, RI, FNR) 
		Wend
		'#End Region
		checkvariables(expr, False, "version", False) 
		Return expr
 	End Method
	
	Method CompOutput(Value:String) 
		_intcode.AddLast(Value) 
	End Method
	Method _BeginCompExpr() 
		_intcode = New TList
		_IntCount = 0
	End Method
	Method GetExprName:String() 
		_IntCount:+1
		Return "@E" + Self._IntCount
	End Method	
	Method CheckVariables:Int(LI:String, FNL:Int, RI:String, FNR:Int) 
		If FNL = False Then
			If GetSufix(LI, False) = "V" And targetscope <> Null Then
				If targetscope.SubEx.CurItem().Contains(LI.ToLower()) = False Then
					Throw "Undefined variable " + LI
				EndIf
			End If
		EndIf
		If FNR = False Then
			If GetSufix(RI, False) = "V" And targetscope <> Null Then
				If targetscope.SubEx.CurItem().Contains(RI.ToLower()) = False Then
					Throw "Undefined variable " + RI
				EndIf
			End If
		EndIf
		Return True
	End Method
	Method CallFunction:String(FuncName:String, Parameterlist:String) 
		Local functionname:String = funcname.tolower() 
		If targetscope = Null Then Return "0"
		If targetscope.Functions.CurItem().Contains(functionname) = False Then
			'Throw("Function " + funcname + " is not defined.")
			'Return "!Err"
			Throw "Undefined function call: " + funcname
			Return "0"
		Else
			'Process parameters
			Local F:BMFunction = BMFunction(Self.TargetScope.Functions.CurItem().ValueForKey(functionname)) 
			If f = Null Then
				Throw "Undefined function call: " + funcname
			End If
			Local C:Int = 0
			For Local p:TParameter = EachIn f.Parameters
				Local dummy:Int = 0
				Local S:String = GetParam(parameterlist, c, dummy) 
				If s <> "" Then
					p.DefaultUsed = False
					Local Res:String = Self._CompEvaluate(GetParam(parameterlist, c, dummy)) 
					If dummy = False And C = f.Parameters.Length - 1 Then
						Throw "Too many parameters."
					End If
					Local isliteral:Int = False
					If GetSufix(Res, False) = "N" Then
						Local leftl:Int = 0, forcenum:Int = 0
						Res = GetLeftId(res, res.Length, Leftl, forcenum) 
						IsLiteral = True
					End If
					If isliteral Then
						Self.CompOutput("PUSHN") 
					Else
						Self.CompOutput("PUSH" + GetSufix(Res, False)) 
					EndIf
					Self.CompOutput(C) 
					Self.CompOutput(Res) 
					Self.CompOutput(0) 
				Else
					p.DefaultUsed = True
					p.Value = p.defaultvalue
					Self.CompOutput("PUSHN") 
					Self.CompOutput(C) 
					Self.CompOutput(p.DefaultValue) 
					Self.CompOutput(1) 
				EndIf
				c:+1
			Next
			Local Ex:String = Self.GetExprName() 
			Self.CompOutput("CALL") 
			Self.CompOutput(Ex) 
			Self.CompOutput(funcname.ToLower()) 
			Return Ex
		End If
	End Method	
End Type

Type TScope
	Field SubEx:TMapStack
	Field functions:TMapStack
	Method New() 
		If subex = Null Then subex = New TMapStack
		If functions = Null Then functions = New TMapStack
		NewScope() 
	End Method
	Method NewScope() 
		SubEx.NewItem() 
		SubEx.CurItem().Insert("true", "1") 
		SubEx.CurItem().Insert("dq", Chr(34)) 
		SubEx.CurItem().Insert("cr", Chr(13) + Chr(10)) 
		SubEx.CurItem().Insert("false", "0") 
		SubEx.CurItem().Insert("version", _Version) 
		functions.NewItem() 
	End Method
	Method DelScope() 
		SubEx.Remove() 
	End Method	
	Method RegisterBMFunction(Name:String, parameters:Tparameter[] , redirect:String(parameters:TParameter[] ) = Null) 
		For Local Prm:TParameter = EachIn parameters
			prm.Name = prm.Name.ToLower() 
		Next
		Local BMF:BMFunction = New BMFunction
		BMF.Parameters = parameters
		bmf.Redirect = redirect
		Functions.curitem().Insert(Name.ToLower(), BMF) 
	End Method

End Type

Type TMapStack
	Field z_Tlist:TList
	Field z_IntCount:Int
	Method New() 
		z_Tlist = New TList
	End Method
	Method NewItem() 
		z_tlist.AddLast(New TMap) 
		z_IntCount:+1
	End Method
	Method CurItem:TMap() 
		Return TMap(z_tlist.Last()) 
	End Method
	Method Remove:TMap() 
		z_tlist.RemoveLast() 
	End Method
	Method Count:Int() 
		Return z_IntCount
	End Method
End Type

Type TExecuter
	Field Scope:TScope = New TScope
	Field ParamPush:TParameter[256] 
	Field LastParam:Int
	Method Execute(Codigo:String[] ) 
		Local SI:Int = 0
		lastparam = -1
		RegisterBuiltInFunctions(scope) 
		While si < codigo.Length
			Select codigo[si] 
				Case "PUSHN"
					Local TP:TParameter = New TParameter
					lastparam = Int(codigo[si + 1] ) 
					ParaMPush[lastparam] = TP
					tp.Value = codigo[si + 2] 
					tp.DefaultUsed = Int(codigo[si + 3] ) 
					si:+3
				Case "PUSHV", "PUSHE"
					Local TP:TParameter = New TParameter
					lastparam = Int(codigo[si + 1] ) 
					ParaMPush[lastparam] = TP
					tp.Value = Self.GetEx(codigo[si + 2] ) 
					tp.DefaultUsed = Int(codigo[si + 3] ) 
					si:+3				
				Case "CALL"
					Local PL:TParameter[lastparam + 1] 
					For Local i:Int = 0 To lastparam
						pl[i] = parampush[i] 
					Next
					Local BF:BMFunction = BMFunction(scope.functions.CurItem().ValueForKey(codigo[si + 2] )) 
					Self.SetEx(codigo[si + 1] , BF.Redirect(pl)) 
					lastparam = -1
					si:+2
				Case "DBG"
					si:+2
				Case "DIVNN"
					Self.SetEx(codigo[si + 1] , Double(codigo[si + 2] ) / Double(codigo[si + 3] )) 
					si:+3
				Case "DIVNE", "DIVNV"
					Self.SetEx(codigo[si + 1] , Double(codigo[si + 2] ) / Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "DIVEN", "DIVVN"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) / Double(codigo[si + 3] )) 
					si:+3
				Case "DIVEE", "DIVVV", "DIVVE", "DIVEV"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) / Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "ANDNN"
					Self.SetEx(codigo[si + 1] , Int(codigo[si + 2] ) & Int(codigo[si + 3] )) 
					si:+3
				Case "ANDNE", "ANDNV"
					Self.SetEx(codigo[si + 1] , Int(codigo[si + 2] ) & Int(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "ANDEN", "ANDVN"
					Self.SetEx(codigo[si + 1] , Int(Self.GetEx(codigo[si + 2] )) & Int(codigo[si + 3] )) 
					si:+3
				Case "ANDEE", "ANDVV", "ANDVE", "ANDEV"
					Self.SetEx(codigo[si + 1] , Int(Self.GetEx(codigo[si + 2] )) & Int(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "ORNN"
					Self.SetEx(codigo[si + 1] , Int(codigo[si + 2] ) | Int(codigo[si + 3] )) 
					si:+3
				Case "ORNE", "ORNV"
					Self.SetEx(codigo[si + 1] , Int(codigo[si + 2] ) | Int(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "OREN", "ORVN"
					Self.SetEx(codigo[si + 1] , Int(Self.GetEx(codigo[si + 2] )) | Int(codigo[si + 3] )) 
					si:+3
				Case "OREE", "ORVV", "ORVE", "OREV"
					Self.SetEx(codigo[si + 1] , Int(Self.GetEx(codigo[si + 2] )) | Int(Self.GetEx(codigo[si + 3] ))) 
					si:+3												
				Case "MULNN"
					Self.SetEx(codigo[si + 1] , Double(codigo[si + 2] ) * Double(codigo[si + 3] )) 
					si:+3
				Case "MULNE", "MULNV"
					Self.SetEx(codigo[si + 1] , Double(codigo[si + 2] ) * Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "MULEN", "MULVN"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) * Double(codigo[si + 3] )) 
					si:+3
				Case "MULEE", "MULVV", "MULVE", "MULEV"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) * Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3		
				Case "SUMNN"
					Self.SetEx(codigo[si + 1] , Double(codigo[si + 2] ) + Double(codigo[si + 3] )) 
					si:+3
				Case "SUMNE", "SUMNV"
					Self.SetEx(codigo[si + 1] , Double(codigo[si + 2] ) + Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "SUMEN", "SUMVN"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) + Double(codigo[si + 3] )) 
					si:+3
				Case "SUMEE", "SUMVV", "SUMVE", "SUMEV"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) + Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3		
				Case "EXPNN"
					Self.SetEx(codigo[si + 1] , Double(codigo[si + 2] ) ^ Double(codigo[si + 3] )) 
					si:+3
				Case "EXPNE", "EXPNV"
					Self.SetEx(codigo[si + 1] , Double(codigo[si + 2] ) ^ Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "EXPEN", "EXPVN"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) ^ Double(codigo[si + 3] )) 
					si:+3
				Case "EXPEE", "EXPVV", "EXPVE", "EXPEV"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) ^ Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "EQSNN"
					Self.SetEx(codigo[si + 1] , codigo[si + 2] = codigo[si + 3] ) 
					si:+3
				Case "EQSNE", "EQSNV"
					Self.SetEx(codigo[si + 1] , codigo[si + 2] = Self.GetEx(codigo[si + 3] )) 
					si:+3
				Case "EQSEN", "EQSVN"
					Self.SetEx(codigo[si + 1] , Self.GetEx(codigo[si + 2] ) = codigo[si + 3] ) 
					si:+3
				Case "EQSEE", "EQSVV", "EQSVE", "EQSEV"
					Self.SetEx(codigo[si + 1] , Self.GetEx(codigo[si + 2] ) = Self.GetEx(codigo[si + 3] )) 
					si:+3
				Case "EQUNN"
					Self.SetEx(codigo[si + 1] , Double(codigo[si + 2] ) = Double(codigo[si + 3] )) 
					si:+3
				Case "EQUNE", "EXPNV"
					Self.SetEx(codigo[si + 1] , Double(codigo[si + 2] ) = Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "EQUEN", "EQUVN"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) = Double(codigo[si + 3] )) 
					si:+3
				Case "EQUEE", "EQUVV", "EQUVE", "EQUEV"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) = Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "GRNN"
					Self.SetEx(codigo[si + 1] , Double(codigo[si + 2] ) > Double(codigo[si + 3] )) 
					si:+3
				Case "GRNE", "GRNV"
					Self.SetEx(codigo[si + 1] , Double(codigo[si + 2] ) > Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "GREN", "GRVN"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) > Double(codigo[si + 3] )) 
					si:+3
				Case "GREE", "GRVV", "GRVE", "GREV"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) > Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "GRENN"
					Self.SetEx(codigo[si + 1] , Double(codigo[si + 2] ) >= Double(codigo[si + 3] )) 
					si:+3
				Case "GRENE", "GRENV"
					Self.SetEx(codigo[si + 1] , Double(codigo[si + 2] ) >= Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "GREEN", "GREVN"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) >= Double(codigo[si + 3] )) 
					si:+3
				Case "GREEE", "GREVV", "GREVE", "GREEV"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) >= Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "SMENN"
					Self.SetEx(codigo[si + 1] , Double(codigo[si + 2] ) <= Double(codigo[si + 3] )) 
					si:+3
				Case "SMENE", "SMENV"
					Self.SetEx(codigo[si + 1] , Double(codigo[si + 2] ) <= Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "SMEEN", "SMEVN"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) <= Double(codigo[si + 3] )) 
					si:+3
				Case "SMEEE", "SMEVV", "SMEVE", "SMEEV"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) <= Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "SMNN"
					Self.SetEx(codigo[si + 1] , Double(codigo[si + 2] ) < Double(codigo[si + 3] )) 
					si:+3
				Case "SMNE", "SMNV"
					Self.SetEx(codigo[si + 1] , Double(codigo[si + 2] ) < Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "SMEN", "SMVN"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) < Double(codigo[si + 3] )) 
					si:+3
				Case "SMEE", "SMVV", "SMVE", "SMEV"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) < Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "GRSNN"
					Self.SetEx(codigo[si + 1] , codigo[si + 2] > codigo[si + 3] ) 
					si:+3
				Case "GRSNE", "GRSNV"
					Self.SetEx(codigo[si + 1] , codigo[si + 2] > Self.GetEx(codigo[si + 3] )) 
					si:+3
				Case "GRSEN", "GRSVN"
					Self.SetEx(codigo[si + 1] , Self.GetEx(codigo[si + 2] ) > codigo[si + 3] ) 
					si:+3
				Case "GRSEE", "GRSVV", "GRSVE", "GRSEV"
					Self.SetEx(codigo[si + 1] , Self.GetEx(codigo[si + 2] ) > Self.GetEx(codigo[si + 3] )) 
					si:+3
				Case "SMSNN"
					Self.SetEx(codigo[si + 1] , codigo[si + 2] < codigo[si + 3] ) 
					si:+3
				Case "SMSNE", "SMSNV"
					Self.SetEx(codigo[si + 1] , codigo[si + 2] < Self.GetEx(codigo[si + 3] )) 
					si:+3
				Case "SMSEN", "SMSVN"
					Self.SetEx(codigo[si + 1] , Self.GetEx(codigo[si + 2] ) < codigo[si + 3] ) 
					si:+3
				Case "SMSEE", "SMSVV", "SMSVE", "SMSEV"
					Self.SetEx(codigo[si + 1] , Self.GetEx(codigo[si + 2] ) < Self.GetEx(codigo[si + 3] )) 
					si:+3
				Case "SUBNN"
					Self.SetEx(codigo[si + 1] , Double(codigo[si + 2] ) - Double(codigo[si + 3] )) 
					si:+3
				Case "SUBNE", "SUBNV"
					Self.SetEx(codigo[si + 1] , Double(codigo[si + 2] ) - Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "SUBEN", "SUBVN"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) - Double(codigo[si + 3] )) 
					si:+3
				Case "SUBEE", "SUBVV", "SUBVE", "SUBEV"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) - Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3
 				Case "STCNN"
					Self.SetEx(codigo[si + 1] , codigo[si + 2] + codigo[si + 3] ) 
					si:+3
				Case "STCNE", "STCNV"
					Self.SetEx(codigo[si + 1] , codigo[si + 2] + Self.GetEx(codigo[si + 3] )) 
					si:+3
				Case "STCEN", "STCVN"
					Self.SetEx(codigo[si + 1] , Self.GetEx(codigo[si + 2] ) + codigo[si + 3] ) 
					si:+3
				Case "STCEE", "STCVV", "STCVE", "STCEV"
					Self.SetEx(codigo[si + 1] , Self.GetEx(codigo[si + 2] ) + Self.GetEx(codigo[si + 3] )) 
					si:+3
				Case "OUTN"
					Print codigo[si + 1] 
					sI:+1
				Case "OUTE", "OUTV"
					Print Self.GetEx(codigo[si + 1] ) 
					sI:+1
				Case "IFN"
				
					If Int(codigo[si + 1] ) = 0 Then
						si = Int(codigo[si + 2] ) - 1
					Else
						si:+2
					End If
				Case "IFE", "IFV"
				
					If Int(Self.GetEx(codigo[si + 1] )) = 0 Then
						si = Int(codigo[si + 2] ) - 1
					Else
						si:+2
					End If
				Case "JMP"
					si = Int(codigo[si + 1] ) - 1

				Case "ALOCV"
					Self.SetEx(codigo[si + 1] , "") 
					si:+1
				Case "SETVN"
					Self.SetEx(codigo[si + 1] , codigo[si + 2] ) 
					si:+2
				Case "SETVE", "SETVV"
					Self.SetEx(codigo[si + 1] , Self.GetEx(codigo[si + 2] )) 
					si:+2
				Case "END"	'Stop program execution
					si = codigo.Length + 1
				Default
					If codigo[si] <> "" Then
						Print "UNKNOWN VIRTUAL MACHINE INDENTIFIER."
						Print "CODE BASE: " + codigo[si] 
						Print "PROGRAM ENDED BY RUN-TIME ERROR"
					Return
					EndIf
			End Select
			si:+1
		Wend
	End Method
	Method SetEx(Name:String, Value:String) 
		Self.scope.SubEx.CurItem().Insert(name.ToLower(), value) 
	End Method
	Method GetEx:String(Name:String) 
		Return String(Self.Scope.SubEx.CurItem().ValueForKey(name.ToLower())) 
	End Method
End Type
Type CompStackItem
	Method SType:String() Abstract
End Type

Type IfStack Extends compstackitem
	Field JumpToCodeLine:Int
	Method SType:String() 
		Return "IF"
	End Method
End Type
Type WhileStack Extends CompStackItem
	Field FirstCodeLine:Int
	Field JumpToCodeLine:Int
	Method SType:String() 
		Return "WHILE"
	End Method
End Type

Type TCompiler
	Field Error_Description:String
	Field Error_SourceCode:String
	Field Error_Line:Int = -1
	Field OutPut:TList
	Field Scope:TScope = New TScope
	Field CompiledLines:Int
	Field ProduceDebug:Int = False
	Field IntStack:CTStack = New CTStack
	Field _LN:Int
	Method New() 
		Output = New TList
	End Method
	Method Compile:String[] (Data:TTextStream) 
		_LN = 0
		RegisterBuiltInFunctions(Self.Scope) 
		'Local LN:Int = 0
		Local Lin:String
		Local OutLin:String
		Try
			While Not Data.Eof() 
				_ln:+1
				Lin = Data.ReadLine() 
				OutLin = Lin	'To get comp output only.
				If InstrB(lin, "'") > 0 Then
					lin = MTrim(Left(lin, Instr(lin, "'") - 1)) 
				End If
				lin = ReplaceB(lin, "(", " ( ") 
				lin = ReplaceB(lin, ")", " ) ") 
				lin = ReplaceB(lin, "[", " [ ") 
				lin = ReplaceB(lin, "]", " ] ") 
				While Asc(lin) > 255 'Avoid a UTF8-BUG ON STREAMS
					lin = Mid(lin, 2) 
				Wend
				lin = MTrim(lin) 
				If Not Begins(lin, "'") And lin <> "" Then
					If ProduceDebug = True
						Self.WriteBCode("DBG") 
						Self.WriteBCode(_ln) 
						Self.WriteBCode(MTrim(OutLin)) 
					End If
				End If
				If Begins(Lin, "'") Or lin = "" Then
					'Nothing! it is a comment!
				ElseIf Begins(lin, "Dim ") Then
					CompVar(Lin) 
				ElseIf Begins(lin, "print ") Then
					compprint(lin) 
				ElseIf Begins(lin, "print(") Then
					compprint("Print " + Mid(lin, 6)) 
				ElseIf lin.ToLower() = "print" Then
					compprint("Print " + Chr(34) + Chr(34)) 
				ElseIf Begins(lin, "if ") Then
					compif(lin) 
				ElseIf lin.ToLower() = "endif" Or lin.ToLower() = "end if" Then
					compendif(lin, _LN) 
				ElseIf lin.ToLower() = "else"
					compelse(lin, _LN) 
				ElseIf lin.ToLower() = "wend"
					compwend(lin, _LN) 
				ElseIf lin.ToLower() = "end" Then
					Self.WriteBCode("END") 
				ElseIf Begins(lin, "while ") 
					compwhile(lin) 
				Else
					If InstrB(Lin, "=") <> 0 Then
						Local Aux:String = MTrim(Left(lin, InstrB(lin, "=") - 1)) 
						If GetSufix(Aux, False) = "V" Then
							CompAssign(Aux, Mid(lin, InstrB(lin, "=") + 1)) 
						Else
							Throw "Syntax error in line " + _LN
						End If
						
					Else
						'DebugStop
						Local dummy:Int = 0
						'Local ev:String = ..
						Self.CompileExpression(lin, dummy) 
					EndIf
				End If
			Wend
			Local SR:String[Output.Count()] 
			For Local i:Int = 0 To sr.Length - 1
				sr[i] = String(Output.ValueAtIndex(i)) 
			Next
			CompiledLines = _LN
			Self._LN = 0
			Return sr
		Catch ex:String
			'Print "Compile Error"
			'Print ex + "(line " + LN + ")"
			'Print Chr(9) + outlin
			Self.Error_Description = ex
			Self.Error_Line = _LN
			Self._LN = 0	'Refreshing
			Self.Error_SourceCode = outlin
			Return Null
		End Try
	End Method
	Method CompPrint(Data:String) 
		data = MTrim(Mid(data, 7)) 
		Local nsufix:Int = 0
		Local Ex:String = Self.CompileExpression(data, Nsufix) 
		If nsufix = False
			Self.WriteBCode("OUT" + GetSufix(ex, False)) 
		Else
			Self.WriteBCode("OUTN") 
		EndIf
		
		Self.writebcode(ex) 
	End Method
	Method CompWhile(Data:String) 
		data = MTrim(Mid(data, 7)) 
		Local WS:WhileStack = New WhileStack
		ws.firstcodeline = output.Count() 
		Local nsufix:Int = 0
		Local Ex:String = Self.CompileExpression(data, Nsufix) 
		If nsufix = False
			Self.WriteBCode("IF" + GetSufix(ex, False)) 
		Else
			Self.WriteBCode("IFN") 
		EndIf
		Self.writebcode(ex) 
		Self.WriteBCode("TOBEERASED") 
		ws.JumpToCodeLine = Self.OutPut.Count() - 1
		Self.IntStack.AddItem(ws) 
	End Method
	Method CompWend(Data:String, LN:Int) 
		Local CS:CompStackItem = CompStackItem(Self.IntStack.GetLastItem()) 
		If cs.SType() <> "WHILE" Then
			Print "Wend is not closing any While."
			Return
		Else
			Local IS:WhileStack = WhileStack(cs) 
			Local JTCL:Int = is.jumptocodeline
			'Print "END IF DIRECTED TO " + String(output.Count())
			Local AUXS:String[] = New String[output.count()] 
			For Local i:Int = 0 To Len(auxs) - 1
				auxs[i] = String(Output.ValueAtIndex(i)) 
			Next
			Auxs[JTCL] = String(output.Count() + 2) 
			Self.OutPut = OutPut.FromArray(Auxs) 
			Self.WriteBCode("JMP") 
			Self.WriteBCode(is.FirstCodeLine) 
			Self.IntStack.RemoveItem() 
		End If
	End Method
	Method Compif(Data:String) 
		data = MTrim(Mid(data, 4)) 
		Local nsufix:Int = 0
		Local Ex:String = Self.CompileExpression(data, Nsufix) 
		If nsufix = False
			Self.WriteBCode("IF" + GetSufix(ex, False)) 
		Else
			Self.WriteBCode("IFN") 
		EndIf
		Local IS:IfStack = New IfStack
		Self.writebcode(ex) 
		Self.WriteBCode("TOBEERASED") 
		is.JumpToCodeLine = Self.OutPut.Count() - 1
		Self.IntStack.AddItem(IS) 
	End Method
	Method compEndIf(Data:String, LN:Int) 
		Local CS:CompStackItem = CompStackItem(Self.IntStack.GetLastItem()) 
		If cs.SType() <> "IF" Then
			Print "End if is not closing any IF."
			Return
		Else
			Local IS:IfStack = IfStack(cs) 
			Local JTCL:Int = is.jumptocodeline
			'Print "END IF DIRECTED TO " + String(output.Count())
			Local AUXS:String[] = New String[output.count()] 
			For Local i:Int = 0 To Len(auxs) - 1
				auxs[i] = String(Output.ValueAtIndex(i)) 
			Next
			Auxs[JTCL] = String(output.Count()) 
			Self.OutPut = OutPut.FromArray(Auxs) 
			Self.IntStack.RemoveItem() 
		End If
	End Method
	Method CompElse(Data:String, LN:Int) 
		Local CS:CompStackItem = CompStackItem(Self.IntStack.GetLastItem()) 
		If cs.SType() <> "IF" Then
			Print "Else is not part of any IF."
			Return
		Else
			Local IS:IfStack = IfStack(cs) 
			Local JTCL:Int = is.jumptocodeline '+2	'Avoid entering the JMP
			Local AUXS:String[] = New String[output.count()] 
			For Local i:Int = 0 To Len(auxs) - 1
				auxs[i] = String(Output.ValueAtIndex(i)) 
			Next
			Auxs[JTCL] = String(output.Count() + 2) 
			Self.OutPut = OutPut.FromArray(Auxs) 
			Self.IntStack.RemoveItem() 
			IS = New IfStack
			Self.writebcode("JMP") 
			Self.WriteBCode("TOBEERASED") 
			is.JumpToCodeLine = Self.OutPut.Count() - 1
			Self.IntStack.AddItem(IS) 
		End If
	End Method		
	Method CompVar(Data:String) 
		Local IsLast:Int = False
		Local Param:Int = 0
		data = MTrim(Mid(data, 5)) 
		Local Vari:String = MTrim(GetParam(data, Param, islast)) 
		Local value:String
		While islast = False
			If Instr(vari, "=") Then
				value = Mid(vari, Instr(vari, "=") + 1) 
				vari = MTrim(Left(vari, Instr(vari, "=") - 1)) 
			Else
				vari = MTrim(vari) 
				value = ""
			End If
			Self.CompNewVar(vari, value) 
			Param:+1
			Vari = GetParam(data, Param, islast) 
		Wend

		If Instr(vari, "=") Then
			value = Mid(vari, Instr(vari, "=") + 1) 
			vari = MTrim(Left(vari, Instr(vari, "=") - 1)) 
		Else
			vari = MTrim(vari) 
			value = ""
		End If
		Self.CompNewVar(vari, value) 
		
	End Method
	Method CompAssign(Varname:String, Expresion:String) 
		If Self.Scope.SubEx.CurItem().Contains(varname.ToLower()) = False Then
			Throw "Undefined target variable " + varname
		EndIf
		Local NSufix:Int = 0
		Local ExpReturn:String = compileexpression(Expresion, nsufix) 
		If nsufix = False Then
			Self.writebcode("SETV" + GetSufix(ExpReturn, False)) 
		Else
			Self.writebcode("SETVN") 
		EndIf
		Self.WriteBCode(VarName) 
		Self.WriteBCode(ExpReturn) 

	End Method
	Method CompNewVar(VarName:String, Value:String) 
		If Self.Scope.SubEx.CurItem().Contains(varname.ToLower()) Then
			Print "DUPLICATE VARIABLE DEFINITION!"
			Return
		End If
		Self.scope.SubEx.CurItem().Insert(varname.ToLower(), varname.ToLower()) 
		If value <> "" Then
			Local NSufix:Int = 0
			Local ExpReturn:String = compileexpression(Value, nsufix) 
			writebcode("ALOCV") 
			writebcode(VarName) 
			If nsufix = False Then
				Self.writebcode("SETV" + GetSufix(ExpReturn, False)) 
			Else
				Self.writebcode("SETVN") 
			EndIf
			Self.WriteBCode(VarName) 
			Self.WriteBCode(ExpReturn) 
		End If
	End Method
	
	Method CompileExpression:String(Expression:String, NSufix:Int Var) 
			Local EV:TCompEvaluator = New TCompEvaluator
			ev.TargetScope = Self.scope
			Local ExpReturn:String = ""
			Local IsLiteral:Int = 0
			Local code:String[] = ev.CompEvaluate(Expression, ExpReturn, IsLiteral) 
			If ev.ErrorDescription <> "" Then
				Throw ev.ErrorDescription
			End If
			For Local i:Int = 0 To code.Length - 1
				Self.WriteBCode(code[i] ) 
			Next
			ev.TargetScope = Null
			ev = Null
			nsufix = isliteral
			Return ExpReturn
	End Method
	
	Method WriteBCode(S:String) 
		Self.OutPut.AddLast(S) 
	End Method
End Type


Type CTStack
	Field Objs:CompStackItem[] 
	Method New() 
		Objs = New CompStackItem[0] 
	End Method
	Method AddItem(Obj:CompStackItem) 
		Objs = objs[..Len(objs) + 1] 
		objs[Len(objs) - 1] = Obj
	End Method
	Method GetLastItem:CompStackItem () 
		Return objs[Len(objs) - 1] 
	End Method
	Method RemoveItem() 
		objs = objs[..Len(objs) - 1] 
	End Method
End Type


'Little function to get a text stream with the correct encoding (unicode, ansi, whatever)
Function LoadStreamText:TTextStream(url:Object) 
	Local format:Int, Size:Int = 0, c:Int, d:Int, e:Int
	Local stream:TStream = ReadStream(url) 
	If stream = Null Then Return Null
	If Not stream.Eof() 
		c = stream.ReadByte() 
		Size:+1
		If Not stream.Eof() 
			d = stream.ReadByte() 
			Size:+1
			If c = $fe And d = $ff
				format = TTextStream.UTF16BE
			Else If c = $ff And d = $fe
				format = TTextStream.UTF16LE
			Else If c = $ef And d = $bb
				If Not stream.Eof() Then
					e = stream.ReadByte() 
					Size:+1
					If e = $bf format = TTextStream.UTF8
				EndIf
			EndIf
		EndIf
	EndIf
	If Not format
		Local Stream2:TTextStream = TTextStream.Create(ReadStream(url), TTextStream.LATIN1) 
		Return Stream2
	EndIf
	stream:TStream = ReadStream(url) 
	Local TStream:TTextStream = TTextStream.Create(stream, format) 
	Return TStream
End Function

'------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
'INTERNALLY USED COMPILER PARSING OPERATIONS:

Const IntSep:String = Chr(34)    'Internal parser separator For literals.
'summary: Replace a substring, ignoring text enclosed in " " and ignoring case.
Function ReplaceB:String(Expr:String, Find:String, ReplaceS:String, Ignorecase:Int = False, RECURSIVE:Int = False) 
	Const TmpChar:String = Chr(27) 
	
	If Not ignorecase Then
		If Instr(expr, find) = 0 Then Return expr
		If InstrB(expr, find) = 0 Then Return expr
		If Instr(expr, IntSep) = 0 Then Return expr.Replace(find, replaceS) 
	EndIf
	Local Aux:String = ""
	Local Flag:Int = False
	Local m:String
	For Local i:Int = 1 To expr.Length
		m = Mid(expr, i, 1) 
		If m = Chr(34) Then
			flag = Not flag
		End If
		If Not flag Then
			aux = aux + M
		Else
			aux = aux + chr(7)
		End If
	Next
	If ignorecase = True Then
		aux = aux.ToLower() 
		find = find.ToLower() 
	EndIf
	Local RETREPLACE:String
	If RECURSIVE = False Then
		RETREPLACE = REPLACES
		ReplaceS = TmpChar
		While Instr(aux, find) <> 0
			Local i:Int = Instr(aux, find) 
			aux = Left(aux, i - 1) + replaceS + Mid(aux, i + find.Length) 
			expr = Left(expr, i - 1) + replaceS + Mid(expr, i + find.Length) 
		Wend
		replaces = retreplace
		find = TmpChar
		While Instr(aux, find) <> 0
			Local i:Int = Instr(aux, find) 
			aux = Left(aux, i - 1) + replaceS + Mid(aux, i + find.Length) 
			expr = Left(expr, i - 1) + replaceS + Mid(expr, i + find.Length) 
		Wend
	Else
		Local OLDFIND:String = ""
		While Instr(AUX, FIND) <> 0
			RETREPLACE = REPLACES
			ReplaceS = TmpChar
			While Instr(aux, find) <> 0
				Local i:Int = Instr(aux, find) 
				aux = Left(aux, i - 1) + replaceS + Mid(aux, i + find.Length) 
				expr = Left(expr, i - 1) + replaceS + Mid(expr, i + find.Length) 
			Wend
			replaces = retreplace
			oldfind = find
			find = TmpChar
			While Instr(aux, find) <> 0
				Local i:Int = Instr(aux, find) 
				aux = Left(aux, i - 1) + replaceS + Mid(aux, i + find.Length) 
				expr = Left(expr, i - 1) + replaceS + Mid(expr, i + find.Length) 
			Wend
			find = oldfind
		Wend
	EndIf
	Return expr
End Function

'summary: Finds a substring, ignoring text enclosed in " " and ignoring case.
Function InstrB:Int(Expr:String, ToFind:String) 
	If Instr(expr, tofind) = 0 Then Return 0
	If Instr(expr, IntSep) = 0 Then Return Instr(expr, tofind) 
	Local Inside:Int = False
	Local Res:String = ""
	For Local i:Int = 1 To expr.Length
		Local M:String = Mid(Expr, i, 1) 
		If M = IntSep Then
			If Inside = False Then Inside = True Else inside = False
		End If
		If inside = True Then M = IntSep
		Res:+M
	Next
	Return Instr(Res, ToFind) 
End Function

'summary: Gets a parameter text in a x,y,z stringby parameter number. It processes properly literals, parenthesis,etc.
Function GetParam:String(Expr:String, count:Int, IsLast:Int Var) 
	Local Opened:Int = False
	Local Parentesi:Int = 0
	Local ParNum:Int = 0
	Local CurParam:String = ""
	For Local i:Int = 1 To expr.Length
		Local SubS:String = Mid(expr, i, 1) 
		If subs = Chr(34) Then opened = Not opened
		If Not opened Then
			If subs = "(" Then
				parentesi:+1
				If parentesi > 0 Then curparam:+subs
			ElseIf subs = ")" Then
				parentesi:-1
				If parentesi >= 0 Then curparam:+subs
			ElseIf subs = "," And parentesi = 0 Then
				ParNum:+1
				If ParNum > count Then
					Return CurParam
				End If
				curparam = ""
			Else
				CurParam:+subs
			EndIf
		Else
			CurParam:+subs
		End If
	Next
	If parnum = count Then
		islast = True
		Return curparam
	Else
		Return ""
	End If
End Function

Function GetLeftId:String(Expr:String, subexindex:Int, chars:Int Var, forceNum:Int Var) 
	Local FName:String = ""
	Forcenum = False
	If Mid(expr, subexindex, 1) = Chr(34) 
		For Local x:Int = subexindex To 0 Step - 1
			fname = Mid(expr, x, 1) + fname
			If x <> subexindex And Mid(expr, x, 1) = Chr(34) Then
				Exit
			EndIf
		Next
		chars = fname.Length
		Forcenum = True
		Return Mid(fname, 2, fname.Length - 2) 
	Else
		For Local x:Int = subexindex To 0 Step - 1
			If IsOperator(Mid(expr, x, 1)) Then
				If Mid(expr, x, 1) = "-" Then
					
					If x = 1 Then
						fname = Mid(expr, x, 1) + fname
					ElseIf x > 1 Then
						If IsOperator(Mid(expr, x - 1, 1)) Then
							fname = Mid(expr, x, 1) + fname
						End If
					End If
				End If
				Exit
			Else
				fname = Mid(expr, x, 1) + fname
			End If
		Next
		chars = fname.Length
		Return fname
	EndIf
End Function

Function GetRightId:String(Expr:String, subexindex:Int, chars:Int Var, ForceNum:Int Var) 
	Forcenum = False
	Local FName:String = ""
	Local minuscount:Int = 0
	Local NotMinus:Int = False
	If Mid(expr, subexindex, 1) = Chr(34) 
		For Local x:Int = subexindex To expr.Length
			fname = fname + Mid(expr, x, 1) 
			If x <> subexindex And Mid(expr, x, 1) = Chr(34) Then
				Exit
			EndIf
		Next
		chars = fname.Length
		forcenum = True
		Return Mid(fname, 2, fname.Length - 2) 
	Else
		For Local x:Int = subexindex To expr.Length
			If IsOperator(Mid(expr, x, 1)) Then
				If Mid(expr, x, 1) = "-" And notminus = False Then
					minuscount:+1
				Else
					Exit
				End If
			Else
				notminus = True
				fname = fname + Mid(expr, x, 1) 
			End If
		Next
		chars = Len(fname) + minuscount
		If minuscount Mod 2 = 1 Then fname = "-" + fname
		Return fname
	EndIf
End Function


'summary: Returns true if a given char is an operator.
Function IsOperator:Int(Char:String) 
	Return (InstrB("+-*/=<>&|^" + TCompEvaluator.AndStr + TCompEvaluator.OrStr, char) <> 0) 
End Function

'summary: Returns true if a given expression is a number.
Function IsNum:Int(Expr:String) 
	Local result:Int = True
	Local decimal:Int = False
	If Left(expr, 1) = Chr(34) Then
		If Right(expr, 1) = Chr(34) Then
			Local Aux:String = Mid(expr, 2, Len(expr) - 2) 
			If Instr(aux, Chr(34)) = 0 Then
				Return True
			End If
		End If
	Else
		For Local x:Int = 1 To expr.Length
			If x = 1 And Mid(expr, x, 1) = "-"
			ElseIf Mid(expr, x, 1) >= "0" And Mid(expr, x, 1) <= "9" Then
			ElseIf Mid(expr, x, 1) = "." And decimal = False
				decimal = True
			Else
				Return False
			End If
		Next
		Return result
	End If
	Return False
End Function

'summary: Returns true if a given expression is a valid variable name.
Function IsVar:Int(Expr:String) 
	Local NoNum:Int = True
	Local digit:String
	For Local x:Int = 1 To expr.Length
		digit = Mid(expr, x, 1).ToUpper() 
		If digit >= "0" And digit <= "9" Then
			If nonum = True Then Return False
		ElseIf digit >= "A" And digit <= "Z"
			nonum = False
		ElseIf digit = "_" Then
			nonum = False
		ElseIf digit = "."
			nonum = True
		Else
			Return False
		End If
	Next
	Return True
End Function

Function IsEx:Int(Expr:String) 
	Local digit:String
	If Left(expr, 2) <> "@E" Then Return False
	If expr.Length <= 2 Then Return False
	For Local i:Int = 3 To expr.Length
		digit = Mid(expr, i, 1).ToUpper() 
		If digit < "0" Or digit > "9" Then
			Return False
		End If
	Next
	Return True
End Function

Function GetSufix:String(Expr:String, Force:Int) 
	If Force = True Then Return "N"
	If IsNum(Expr) Then Return "N"
	If IsVar(Expr) Then Return "V"
	If IsEx(Expr) Then Return "E"
	Throw "syntax error in expression: " + Expr + " is not a valid identifier."
	Return "#"	'->Runtime error will be generated!
End Function

'summary: Returns true if a given string begins with a given value ignoring case
Function Begins:Int(Str1:String, str2:String) 
	Local L:Int = Str2.Length
	Return Left(str1.ToLower(), L) = str2.ToLower() 
End Function

'summary: Returns true if a given string ends with a given value ignoring case
Function Ends:Int(Str1:String, Str2:String) 
	Local L:Int = Str2.Length
	Return Right(str1.ToLower(), L) = str2.ToLower() 
End Function

'summary: Returns the same given string but striping spaces and tabs at the end and at the begining of the string.
Function MTrim:String(Str:String) 
 	str = ReplaceB(str, Chr(9), " ") 
	While InstrB(str, "  ") 
		str = ReplaceB(str, "  ", " ") 
	Wend
	str = Trim(str) 
	Return Str
End Function

'------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
'EXTERNAL FUNCTIONS HANDLERS:
'#Region: Types to handle external BMX functions:
'summary: This type handles a BMX function from within the script. Each function has to be registered in the script language.
Type BMFunction
	'summary: This is the name of the function in the script language.
	Field Name:String
	'This is an array that describes each parameter of the function, by order.
	Field Parameters:TParameter[] 
	'This is a pointer to the compiled function to be called when the script requieres it.
	Field Redirect:String(parameters:TParameter[] ) 
End Type

'summary: This is the base class for all parameters in a function declaration
Type TParameter
	'summary: This is the name of the parameter.
	Field Name:String = "<Void>"
	'summary: This is the value of the parameter in the current function call.<br>This field will be automatically filled by the evaluator before a function call is requested.
	Field Value:String = ""
	'summary: This field contains the default value for this parameter.<br>This value will be automatically selected when a function call is performed and the parameter in question is missing.
	Field DefaultValue:String = ""
	'summary: This is a boolean field that indicates if this parameter was missing or not when the function call was performed.
	Field DefaultUsed:Int = False
End Type
'------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
'BUILT IN FUNCTIONS:
'Each function that can be invoked from the Script langua, has to have the following
'declaration under BMX:
'Function FunctionName:String(Paramenters:Tparameter[])
'All functions return STRINGS, as the script language handles all its data
'using STRINGS. The Parameters[] array will contain each TParameter stated at execution time on the script.
'Example:
'	Function MathCos:String(parameters:Tparameter[] ) 
'		Local Value:Double = Double(Parameters[0].Value)	'Get the value and convert it to numeric
'		Value = Cos(Value)									'Perform calculation
'		Return String(Value)								'Return it as a string
'	End Function
'This function returns the cosinus of the first given parameter.
'As the value field in the parameter[0] object is a string, to make the calculation
'we first convert it to double. Then calculate the COS, and return it as string.
	Function MathCos:String(parameters:Tparameter[] ) 
		Return String(Cos(Double(parameters[0].Value))) 
	End Function
	
	Function MathTan:String(parameters:Tparameter[] ) 
		Return String(Tan(Double(parameters[0].Value))) 
	End Function
	
	Function MathSin:String(parameters:Tparameter[] ) 
		Return String(Sin(Double(parameters[0].Value))) 
	End Function

	Function MathACos:String(parameters:Tparameter[] ) 
		Return String(ACos(Double(parameters[0].Value))) 
	End Function
	
	Function MathATan:String(parameters:Tparameter[] ) 
		Return String(ATan(Double(parameters[0].Value))) 
	End Function
	
	Function MathASin:String(parameters:Tparameter[] ) 
		Return String(ASin(Double(parameters[0].Value))) 
	End Function
'#Region Hiperbolic Sin/Cos/Tan
	Function MathCosh:String(parameters:Tparameter[] ) 
		Return String(Cosh(Double(parameters[0].Value))) 
	End Function
	
	Function MathTanh:String(parameters:Tparameter[] ) 
		Return String(Tanh(Double(parameters[0].Value))) 
	End Function
	
	Function MathSinh:String(parameters:Tparameter[] ) 
		Return String(Sinh(Double(parameters[0].Value))) 
	End Function
'#End Region

Function MathATan2:String(parameters:Tparameter[] ) 
	Return String(ATan2(Double(parameters[0].Value), Double(parameters[1].Value))) 
End Function

Function MathCeil:String(parameters:Tparameter[] ) 
	Return String(Ceil(Double(parameters[0].Value))) 
End Function

Function Version:String(parameters:Tparameter[] ) 
	Return _Version
End Function

Function MathSQR:String(parameters:Tparameter[] ) 
	Return String(Sqr(Double(parameters[0].Value))) 
End Function

Function MathLog:String(parameters:Tparameter[] ) 
	Return String(Log(Double(parameters[0].Value))) 
End Function

Function MathLog10:String(parameters:Tparameter[] ) 
	Return String(Log10(Double(parameters[0].Value))) 
End Function

Function MathIsNan:String(parameters:Tparameter[] ) 
	Return String(IsNan(Double(parameters[0].Value))) 
End Function

Function MathIsInf:String(parameters:Tparameter[] ) 
	Return String(IsInf(Double(parameters[0].Value))) 
End Function

Function MathFloor:String(parameters:Tparameter[] ) 
	Return String(Floor(Double(parameters[0].Value))) 
End Function

Function MathExp:String(parameters:Tparameter[] ) 
	Return String(Exp(Double(parameters[0].Value))) 
End Function

Function MathMult:String(parameters:Tparameter[] ) 
	Return String(Double(parameters[0].Value) * Double(parameters[1].Value)) 
End Function

Function MathInt:String(parameters:Tparameter[] ) 
	If Int(Parameters[1].Value) = 1 Then
		parameters[0].Value = String(Double(parameters[0].Value) +.5) 
	End If
	Return String(Int(parameters[0].Value)) 
End Function

Function BSMillisecs:String(parameters:Tparameter[] ) 
	Return String(MilliSecs()) 
End Function

Function BSChr:String(parameters:Tparameter[] ) 
	Return Chr(Int(parameters[0].Value)) 
End Function

Function BSAsc:String(parameters:Tparameter[] ) 
	Return Asc(parameters[0].Value) 
End Function

Function BSLeft:String(parameters:Tparameter[] ) 
	Return Left(parameters[0].value, Int(parameters[1].value)) 
End Function

Function BSRight:String(parameters:Tparameter[] ) 
	Return Right(parameters[0].value, Int(parameters[1].value)) 
End Function

Function BSMid:String(parameters:Tparameter[] ) 
	Return Mid(parameters[0].value, Int(parameters[1].value), Int(Parameters[2].value)) 
End Function

Function Lcase:String(parameters:Tparameter[] ) 
	Return Parameters[0].Value.ToLower() 
End Function

Function UCase:String(parameters:Tparameter[] ) 
	Return Parameters[0].Value.ToUpper() 
End Function

Function BsInput:String(parameters:Tparameter[] ) 
	Return Input(parameters[0].value) 
End Function

Function BsNot:String(parameters:Tparameter[] ) 
	Return String(Not Int(parameters[0].value)) 
End Function

Function BSRand:String(parameters:Tparameter[] ) 
	Return Rand(Int(Parameters[0].Value), Int(parameters[1].Value)) 
End Function

Function BSSeedRnd:String(parameters:Tparameter[] ) 
	SeedRnd(Int(parameters[0].Value)) 
	Return "1"
End Function

Function RegisterBuiltInFunctions(ev:Tscope) 
	ev.registerbmfunction("Millisecs", Null, BSMillisecs) 
	ev.registerbmfunction("Version", Null, Version) 
	'Register the SIN function:
	Local P:TParameter[1] 	'Parameter array of 1 item
	p[0] = New TParameter	'Instantiate the first parameter
	p[0].Name = "Angle"		'Name of the parameter
	p[0].DefaultValue = ""	'No default value for this parameter
	ev.RegisterBMFunction("Sin", p, MathSin) 	'The function is registered in the evaluator object.
	'The same for the COS function:
	p = New TParameter[1] 
	p[0] = New TParameter
	p[0].Name = "Angle"
	ev.RegisterBMFunction("Cos", p, MathCos) 
	'The same for the TAN function:
	p = New TParameter[1] 
	p[0] = New TParameter
	p[0].Name = "Angle"
	ev.RegisterBMFunction("Tan", p, MathTan) 
	'The same for the ASIN function:
	p = New TParameter[1] 
	p[0] = New TParameter
	p[0].Name = "Angle"
	ev.RegisterBMFunction("ASin", p, MathASin) 
	'The same for the ACOS function:
	p = New TParameter[1] 
	p[0] = New TParameter
	p[0].Name = "Angle"
	ev.RegisterBMFunction("ACos", p, MathACos) 
	'The same for the ATAN function:
	p = New TParameter[1] 
	p[0] = New TParameter
	p[0].Name = "Angle"
	ev.RegisterBMFunction("ATan", p, MathATan) 
	'The same for the SINH function:
	p = New TParameter[1] 
	p[0] = New TParameter
	p[0].Name = "Angle"
	ev.RegisterBMFunction("SinH", p, MathSinh) 
	'The same for the COSH function:
	p = New TParameter[1] 
	p[0] = New TParameter
	p[0].Name = "Angle"
	ev.RegisterBMFunction("CosH", p, MathCosh) 
	'The same for the TANH function:
	p = New TParameter[1] 
	p[0] = New TParameter
	p[0].Name = "Angle"
	ev.RegisterBMFunction("TanH", p, MathTanh) 
	'The same for the ATAN2 function:
	p = New TParameter[2] 
	p[0] = New TParameter
	p[0].Name = "Angle"
	p[1] = New TParameter
	p[1].Name = "Angle2"
	ev.RegisterBMFunction("ATan2", p, MathATan2) 
	'The same for the TAN function:
	p = New TParameter[1] 
	p[0] = New TParameter
	p[0].Name = "Value"
	ev.RegisterBMFunction("Ceil", p, MathCeil) 
	'The same for the INT function:
	p = New TParameter[2] 
	p[0] = New TParameter
	p[0].Name = "Value"
	p[1] = New TParameter
	p[1].Name = "Round"
	p[1].DefaultValue = True
	ev.RegisterBMFunction("Int", p, MathInt) 
	'Register the Mult function, with 2 parameters, the second one optional.
	p = New TParameter[2] 	'We instantiate the parameter array
	p[0] = New TParameter	'Instantiate the first parameter
	p[0].Name = "Num1"		'Name of the first parameter
	p[1] = New TParameter	'Instantiate the second parameter
	p[1].Name = "Num2"		'Name of the second parameter
	p[1].DefaultValue = 2	'Default value of the second parameter
	ev.RegisterBMFunction("Mult", p, MathMult)  	'The function is registered in the evaluator object.
	'Function MathSQR:String(parameters:Tparameter[], Evaluator:TEvaluator)
	p = New TParameter[1] 
	p[0] = New TParameter
	p[0].Name = "Value"
	ev.RegisterBMFunction("Sqr", p, MathSQR) 
	'Function MathLog:String(parameters:Tparameter[], Evaluator:TEvaluator)
	p = New TParameter[1] 
	p[0] = New TParameter
	p[0].Name = "Value"
	ev.RegisterBMFunction("Log", p, MathLog) 
	'Function MathLog10:String(parameters:Tparameter[], Evaluator:TEvaluator)
	p = New TParameter[1] 
	p[0] = New TParameter
	p[0].Name = "Value"
	ev.RegisterBMFunction("Log10", p, MathLog10) 
	'Function MathIsNan:String(parameters:Tparameter[], Evaluator:TEvaluator)
	p = New TParameter[1] 
	p[0] = New TParameter
	p[0].Name = "Value"
	ev.RegisterBMFunction("IsNaN", p, MathIsNan) 
	'Function MathIsInf:String(parameters:Tparameter[], Evaluator:TEvaluator)
	p = New TParameter[1] 
	p[0] = New TParameter
	p[0].Name = "Value"
	ev.RegisterBMFunction("IsInf", p, MathIsInf) 
	'Function MathFloor:String(parameters:Tparameter[], Evaluator:TEvaluator)
	p = New TParameter[1] 
	p[0] = New TParameter
	p[0].Name = "Value"
	ev.RegisterBMFunction("Floor", p, MathFloor) 
	'Function MathExp:String(parameters:Tparameter[], Evaluator:TEvaluator)
	p = New TParameter[1] 
	p[0] = New TParameter
	p[0].Name = "Value"
	ev.RegisterBMFunction("Exp", p, MathExp) 
	'Register the chr function:
	p = New TParameter[1] 
	p[0] = New TParameter	'Instantiate the first parameter
	p[0].Name = "CharNum"		'Name of the parameter
	p[0].DefaultValue = ""	'No default value for this parameter
	ev.RegisterBMFunction("Chr", p, BSChr) 	'The function is registered in the evaluator object.
	'Register the Asc function:
	p = New TParameter[1] 
	p[0] = New TParameter	'Instantiate the first parameter
	p[0].Name = "Char"		'Name of the parameter
	p[0].DefaultValue = ""	'No default value for this parameter
	ev.RegisterBMFunction("Asc", p, BSAsc) 	'The function is registered in the evaluator object.
	'Function BSLeft:String(parameters:Tparameter[], Evaluator:TEvaluator)
	p = New TParameter[2] 	'We instantiate the parameter array
	p[0] = New TParameter	'Instantiate the first parameter
	p[0].Name = "Variable"		'Name of the first parameter
	p[1] = New TParameter	'Instantiate the second parameter
	p[1].Name = "Length"		'Name of the second parameter
	p[1].DefaultValue = 1	'Default value of the second parameter
	ev.RegisterBMFunction("Left", p, BSLeft) 
	'Function BSRight:String(parameters:Tparameter[], Evaluator:TEvaluator)
	p = New TParameter[2] 	'We instantiate the parameter array
	p[0] = New TParameter	'Instantiate the first parameter
	p[0].Name = "Variable"		'Name of the first parameter
	p[1] = New TParameter	'Instantiate the second parameter
	p[1].Name = "Length"		'Name of the second parameter
	p[1].DefaultValue = 1	'Default value of the second parameter
	ev.RegisterBMFunction("Right", p, BSRight) 
	'Function BSMid:String(parameters:Tparameter[], Evaluator:TEvaluator)
	p = New TParameter[3] 	'We instantiate the parameter array
	p[0] = New TParameter	'Instantiate the first parameter
	p[0].Name = "Variable"		'Name of the first parameter
	p[1] = New TParameter	'Instantiate the second parameter
	p[1].Name = "Start"		'Name of the second parameter
	p[1].DefaultValue = 1	'Default value of the second parameter
	p[2] = New TParameter	'Instantiate the second parameter
	p[2].Name = "Length"		'Name of the second parameter
	p[2].DefaultValue = -1	'Default value of the second parameter
	ev.RegisterBMFunction("Mid", p, BSMid) 
	'Function Lcase:String(parameters:Tparameter[], Evaluator:TEvaluator)
	p = New TParameter[1] 
	p[0] = New TParameter	'Instantiate the first parameter
	p[0].Name = "Value"		'Name of the parameter
	p[0].DefaultValue = ""	'No default value for this parameter
	ev.RegisterBMFunction("LCase", p, Lcase) 
	'Function UCase:String(parameters:Tparameter[], Evaluator:TEvaluator)
	p = New TParameter[1] 
	p[0] = New TParameter	'Instantiate the first parameter
	p[0].Name = "Value"		'Name of the parameter
	p[0].DefaultValue = ""	'No default value for this parameter
	ev.RegisterBMFunction("UCase", p, UCase) 
	'Function Input:String(parameters:Tparameter[], Evaluator:TEvaluator)
	p = New TParameter[1] 
	p[0] = New TParameter	'Instantiate the first parameter
	p[0].Name = "Prompt"		'Name of the parameter
	p[0].DefaultValue = ">"	'No default value for this parameter
	ev.RegisterBMFunction("Input", p, BsInput) 
	'Function Input:String(parameters:Tparameter[], Evaluator:TEvaluator)
	p = New TParameter[1] 
	p[0] = New TParameter	'Instantiate the first parameter
	p[0].Name = "Value"		'Name of the parameter
	p[0].DefaultValue = "1"	'No default value for this parameter
	ev.RegisterBMFunction("Not", p, BsNot) 
	'The same for the RAND function:
	p = New TParameter[2] 
	p[0] = New TParameter
	p[0].Name = "MinValue"
	p[1] = New TParameter
	p[1].Name = "MaxValue"
	ev.RegisterBMFunction("Rand", p, BSRand) 
	'SEDDRND
	p = New TParameter[1] 
	p[0] = New TParameter	'Instantiate the first parameter
	p[0].Name = "Value"		'Name of the parameter
	p[0].DefaultValue = "1"	'No default value for this parameter
	ev.RegisterBMFunction("SeedRnd", p, BSSeedRnd) 
End Function

Comments

Azathoth2007
It got cut off


ziggy2007
I've updated it (deleted some blank lines) so it now is not cut off here.


_332007
This is one reason to go Bmax, this stuff is efficient. Doing the same in Blitz3D doesn't work as well, or as fast.


Perturbatio2007
I left it compiling for about 10 minutes and there was no result. :(


ziggy2007
Perturbation: Did you check the console? The example is a command line application


Azathoth2007
I'm getting the same problem as Perturbatio, I tracked it down to ResplaceB getting in an infinite loop or something.
This was on compiling the first example


ziggy2007
There was a spetial char in the code that was modified to a URL encoded char by the blitzmax website. I've changed the code to use chr function for this internal control char and now it works properly.


_332007
...
				Case "DIVEN", "DIVVN"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) / Double(codigo[si + 3] )) 
					si:+3
				Case "DIVEE", "DIVVV", "DIVVE", "DIVEV"
					Self.SetEx(codigo[si + 1] , Double(Self.GetEx(codigo[si + 2] )) / Double(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "ANDNN"
					Self.SetEx(codigo[si + 1] , Int(codigo[si + 2] ) & Int(codigo[si + 3] )) 
					si:+3
				Case "ANDNE", "ANDNV"
					Self.SetEx(codigo[si + 1] , Int(codigo[si + 2] ) & Int(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "ANDEN", "ANDVN"
					Self.SetEx(codigo[si + 1] , Int(Self.GetEx(codigo[si + 2] )) & Int(codigo[si + 3] )) 
					si:+3
				Case "ANDEE", "ANDVV", "ANDVE", "ANDEV"
					Self.SetEx(codigo[si + 1] , Int(Self.GetEx(codigo[si + 2] )) & Int(Self.GetEx(codigo[si + 3] ))) 
					si:+3
				Case "ORNN"
...

ziggy, I'd be inclined to change all those case an codes into a form of jump table. That should make for a nice speed enhancement.


ziggy2007
Oh yes, there's A LOT of thinks that are not made in a decent way! It is not creating real byte code, it is string-based code, etc. I wasn't trying to make a real virtual machine, as I said, it was just a test I made in a couple of evenings to see where could I get, and that's the result. If I ever make a Virtual Machine (In fact I'm writing a REAL one), all the execution will be byte-code based and, of course, a jump table will be used there.


Filax2007
Impressive Ziggy ! :) But it is possible to some pass vars between
max app => script ? Because the script seem to run himself
without communication with bmax application except for print ?
or i'm wrong ?


ziggy2007
The ultra lite script can call functions created on the host blitzmax app, and all the script variable values are alocated on a TMAP object in the script engine, so yes, they can comunicate to each other without any problem.

Example:
'This is a function to convert a string to its uppercase:
Function UCase:String(parameters:Tparameter[] ) 
	Return Parameters[0].Value.ToUpper() 
End Function

'This function is now registered to be 'callable' from the script:
local p:TParameter[] = New TParameter[1] 
	p[0] = New TParameter	'Instantiate the first parameter
	p[0].Name = "Value"		'Name of the parameter
	p[0].DefaultValue = ""	'No default value for this parameter
	ev.RegisterBMFunction("UCase", p, UCase)  'Parameters:  Name, ParamArray, BlitzMax Function Pointer.


In this example, the object EV has to be a TScope object.


This script engine is not suitable for fast scripting, it is very slow, no jump table, no real variable adresses etc. not really a virtual machine, but it has the bare bones to create a real one. In fact I'm starting to create a real one all written in BM. If I ever finish it I will release it as a module.


Code Archives Forum