Code archives/Algorithms/ultra lite script language
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
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
| ||
It got cut off |
| ||
I've updated it (deleted some blank lines) so it now is not cut off here. |
| ||
This is one reason to go Bmax, this stuff is efficient. Doing the same in Blitz3D doesn't work as well, or as fast. |
| ||
I left it compiling for about 10 minutes and there was no result. :( |
| ||
Perturbation: Did you check the console? The example is a command line application |
| ||
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 |
| ||
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. |
| ||
... 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. |
| ||
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. |
| ||
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 ? |
| ||
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