How to run a string?
Re: How to run a string?
They're here now:
http://sourceforge.net/projects/fbc/fil ... Libraries/
(I didn't update them for the 1.00.0 release, because it's way too much work)
By the way, you can probably also find the precompiled Lua library on the Lua homepage:
http://lua-users.org/wiki/LuaBinaries
http://luabinaries.sourceforge.net/download.html
e.g., for FB-win32, you'd probably have to download the "Windows x86 (MingW 4 Compatible)" package.
http://sourceforge.net/projects/fbc/fil ... Libraries/
(I didn't update them for the 1.00.0 release, because it's way too much work)
By the way, you can probably also find the precompiled Lua library on the Lua homepage:
http://lua-users.org/wiki/LuaBinaries
http://luabinaries.sourceforge.net/download.html
e.g., for FB-win32, you'd probably have to download the "Windows x86 (MingW 4 Compatible)" package.
Re: How to run a string?
Thanks dkl.
I got both, the dll from lua site, the static from dkl's freebasic link.
However, running the code gives:
Using disphelper, and adjusting Rock's code, VIZ:
I get
I got both, the dll from lua site, the static from dkl's freebasic link.
However, running the code gives:
Code: Select all
-11 0
-10 0
-9 0
-8 0
-7 0
-6 0
-5 0
-4 0
-3 0
-2 0
-1 0
0 0
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 0
10 0
11 0
Programm-Ende
Code: Select all
'==== SETUP disphelper ==================
#define UNICODE
#include Once "disphelper/disphelper.bi"
Dim shared as IDISPATCH PTR VB_FB
dhInitialize(TRUE)
dhToggleExceptions(True)
dhCreateObject "MSScriptControl.ScriptControl",NULL,@VB_FB
dhPutValue VB_FB,".Language %s","VBScript"
Sub _END() destructor
SAFE_RELEASE(VB_FB)
dhUninitialize True
End Sub
Function FindAndReplace(S as string,F as string,R as string)as string
Dim Ret as zstring ptr
dhGetValue "%s",@Ret,VB_FB,".Eval %s","Replace("""+S+""","""+F+""","""+R+""")"
Return *Ret
End Function
Function eval(s As String) As Double
Dim value As Zstring Ptr
dhGetValue "%s",@value,VB_FB,".Eval %s",s
Return Val(*value)
End Function
Function LoadFile(ByRef filename As String) As String
Dim h As Integer
Dim txt As String
h = FreeFile
If Open( filename For Binary Access Read As #h ) <> 0 Then Return "File not found"
If LOF(h) > 0 Then
txt = String(LOF(h), 0)
If Get( #h, ,txt ) <> 0 Then txt = ""
End If
Close #h
Return txt
End Function
dim as string s=Loadfile("formula.lua")
s=FindAndReplace(s,"y=","")
For x As Integer=-11 To 11
Print x,
var s2=FindAndReplace(s,"x",str(x))
print eval(s2)
Next
PRINT "Programm-Ende"
sleep
Code: Select all
-11 112
-10 92
-9 74
-8 58
-7 44
-6 32
-5 22
-4 14
-3 8
-2 4
-1 2
0 2
1 4
2 8
3 14
4 22
5 32
6 44
7 58
8 74
9 92
10 112
11 134
Programm-Ende
Re: How to run a string?
This seems to work:
And from RockTheSchock (using a string instead of a file):
Code: Select all
'y=x^2+x+2 is the include file
dim as double y
For x As Integer=-11 To 11
#include once "formula.lua"
print x,
print y
next x
PRINT "Programm-Ende"
sleep
Code: Select all
#INCLUDE ONCE "Lua/lua.bi"
#INCLUDE ONCE "Lua/lauxlib.bi"
'#INCLUDE ONCE "Lua/lualib.bi"
function Evaluate(byval Expression as string,StringVariable as string,DoubleVariable as double,byref lua as lua_state ptr) as double
lua_pushnumber(Lua, DoubleVariable)
lua_setglobal(Lua, StringVariable)
luaL_dostring(Lua,Expression)
lua_getglobal(Lua,left(Expression,1))
Evaluate= lua_tonumber(Lua, 0)
lua_pop(Lua, 1)
end function
DIM Lua AS lua_State PTR = luaL_newstate ' Schnittstelle zu Lua
'luaL_requiref (lua,LUA_MATHLIBNAME,@luaopen_math,1) 'sandboxing only math allowed
dim as string s="y=x^2+x+2"
For x As double=-11 To 11 step .5
Print x,Evaluate(s,"x",x,lua)
Next
PRINT "Programm-Ende"
lua_close Lua ' Lua-State freigeben
Sleep
-
- Posts: 252
- Joined: Mar 12, 2006 16:25
Re: How to run a string?
The basic lua implementation is 5x faster then the disphelper implementation. With a precompiled function the lua code gets even 10x faster.(50x faster then disphelper)
EDIT: made some corrections with stack and lua_pop
If you wanna know about the stack read this :
http://stackoverflow.com/questions/1844 ... r-18451429
EDIT: made some corrections with stack and lua_pop
Code: Select all
#Include Once "Lua/lua.bi"
#Include Once "Lua/lauxlib.bi"
#Include Once "Lua/lualib.bi"
Function Evaluate(ResultVariable As String,ByVal Expression As String,StringVariable As String,DoubleVariable As Double,ByRef lua As lua_state Ptr) As Double
lua_pushnumber(Lua, DoubleVariable)
lua_setglobal(Lua, StringVariable)
luaL_dostring(Lua,ResultVariable+"="+Expression)
lua_getglobal(Lua,ResultVariable)
Evaluate = lua_tonumber(Lua, -1)
lua_pop(Lua, 1)
End Function
Function Evaluate2(fname As String,ByVal Expression As String,StringVariable As String,DoubleVariable As Double,ByRef lua As lua_state Ptr) As Double
Static func As String
If Len(func)=0 Then 'setup and compile function
func = "function " + fname +"("+StringVariable+")" +Chr(13)+Chr(10) _
+ " return " + Expression +Chr(13)+Chr(10) _
+ "end"
Print
Print "Setting up Function:"
Print func
If luaL_dostring(Lua,func) Then
PRINT "Error: " & *lua_tostring(Lua, -1),__LINE__
sleep
EndIf
EndIf
lua_getglobal(Lua, fname)
lua_pushnumber(Lua, DoubleVariable)
IF lua_pcall(Lua, 1, 1, 0) Then
Print "Error: " & *lua_tostring(Lua, -1),__LINE__
sleep
EndIf
Evaluate2 = lua_tonumber(Lua, -1)
lua_pop(Lua, 1)
End Function
Dim Lua As lua_State Ptr = luaL_newstate ' Schnittstelle zu Lua
Dim As String e="x^2+x+2"
Dim t As Double
Print "Evaluate"
t=Timer
For x As Double=-11000 To 11000 Step 0.1
Evaluate("y",e,"x",x,lua)
Next
t=Timer-t
Print Using "Elapsed time: #.## seconds"; t
Print
Print "Evaluate2"
t=Timer
For x As Double=-11000 To 11000 Step 0.1
Evaluate2("f",e,"x",x,lua)
Next
t=Timer-t
Print Using "Elapsed time: #.## seconds"; t
Print "Programm-Ende"
Print lua_gettop(lua)
lua_close Lua ' Lua-State freigeben
Sleep
http://stackoverflow.com/questions/1844 ... r-18451429
Re: How to run a string?
Thank you RockTheSchock, interesting stuff.
I might have a practise with the lua library, seems fast.
Surprisingly, just using #include is very fast:
I might have a practise with the lua library, seems fast.
Surprisingly, just using #include is very fast:
Code: Select all
'y=x^2+x+2 is the include file
dim as double y
dim as double t=timer
For x As double=-11000 To 11000 Step 0.1
#include once "formula.lua"
if x=-6964.399999985319 then print y
next x
PRINT "Programm-Ende",y
print "Time taken ";timer-t
sleep
Re: How to run a string?
Of course:dodicat wrote:Surprisingly, just using #include is very fast
#include is a preprocessor statement to include contents of another source file.
This is realized during compilation phase.
Therefore execution time is not impacted.
Re: How to run a string?
So, formula.lua is only loaded once, and depending where in your code you place #include "formula.lua", it is put there, inline.
This makes the code very fast, at least 10 times faster than a function call.
I do remember dkl discussing inline functions a while back.
This makes the code very fast, at least 10 times faster than a function call.
I do remember dkl discussing inline functions a while back.
Re: How to run a string?
@dodicat
#INCLUDE code segments get imported to the source code before compiling (pre-process). This isn't related to inline-functions, which are macros (#DEFINEs) that return a value.
You can compile with option -pp to see what happens in your code.
#INCLUDE code segments get imported to the source code before compiling (pre-process). This isn't related to inline-functions, which are macros (#DEFINEs) that return a value.
You can compile with option -pp to see what happens in your code.
-
- Posts: 252
- Joined: Mar 12, 2006 16:25
Re: How to run a string?
The thing about embedding lua is, you dont need to compile your freebasic code anymore. So if you want dynamicly created/inputed/loaded formulas you need to compile/interpret them. If you bundle the freebasic compiler with your application your application will be huge. You will eventually also have a problem with the license. If your application depends on freebasic to run properly you have to use gpl licence for your program, too.
If you use lua just a copyright notice in the program or its documentation is enough. If you need a formula eval function to draw simple graphs or to make some sort of table calculation sheet i would use lua. The size of your programm will be just 200kb bigger with lua embedded. In lua you could also make create a sandbox enviroment, so the worst thing that can happen is that the lua formula eats CPU or RAM resources, but it wont corrupt your harddisk or files:
http://stackoverflow.com/questions/1224 ... er-6982080
i made it even 2.5X faster using a for loop within lua which calls the formula function. The results are passed by calling a CDECL function from lua which then stores the values to a shared array.
If you use lua just a copyright notice in the program or its documentation is enough. If you need a formula eval function to draw simple graphs or to make some sort of table calculation sheet i would use lua. The size of your programm will be just 200kb bigger with lua embedded. In lua you could also make create a sandbox enviroment, so the worst thing that can happen is that the lua formula eats CPU or RAM resources, but it wont corrupt your harddisk or files:
http://stackoverflow.com/questions/1224 ... er-6982080
i made it even 2.5X faster using a for loop within lua which calls the formula function. The results are passed by calling a CDECL function from lua which then stores the values to a shared array.
Code: Select all
#Include Once "Lua/lua.bi"
#Include Once "Lua/lauxlib.bi"
#Include Once "Lua/lualib.bi"
Declare Sub EvaluateForAndCall(fname As String,ByVal Expression As String,StringVariable As String,DoubleVariable As Double,ByRef lua As lua_state Ptr,startx As Double,stopx As Double, stepx As Double)
Declare Function Evaluate2(fname As String,ByVal Expression As String,StringVariable As String,DoubleVariable As Double,ByRef lua As lua_state Ptr) As Double
Declare Function Evaluate(ResultVariable As String,ByVal Expression As String,StringVariable As String,DoubleVariable As Double,ByRef lua As lua_state Ptr) As Double
Dim As Double startx=-11000,stopx=110000,stepx=0.1
'Dim As Double startx=-11,stopx=11,stepx=0.5
Type PointType
x As Double
y As Double
End Type
ReDim Shared result((stopx-startx)/stepx) As PointType
Dim Lua As lua_State Ptr = luaL_newstate ' Schnittstelle zu Lua
luaL_openlibs(Lua)
Dim As String e="x^2+x+2"
Dim t As Double
Print "----------------------"
Print "EvaluateForAndCall"
Print "----------------------"
t=Timer
EvaluateForAndCall("f",e,"x",0,lua,startx,stopx,stepx)
Dim calculatesomething As Double
For i as integer = LBound(result) To UBound(result)
calculatesomething=result(i).x+result(i).y
Next
t=Timer-t
Print Using "Elapsed time: #.## seconds"; t
Print
Print
Print "----------------------"
Print "Evaluate"
Print "----------------------"
t=Timer
For x As Double=startx To stopx Step stepx
'Print Evaluate("y",e,"x",x,lua)
Evaluate("y",e,"x",x,lua)
Next
t=Timer-t
Print Using "Elapsed time: #.## seconds"; t
Print
Print
Print "----------------------"
Print "Evaluate2"
Print "----------------------"
t=Timer
For x As Double=startx To stopx Step stepx
'Print Evaluate2("f",e,"x",x,lua)
Evaluate2("f",e,"x",x,lua)
Next
t=Timer-t
Print Using "Elapsed time: #.## seconds"; t
Print
Print
Print "Programm-Ende"
lua_close Lua ' Lua-State freigeben
Sleep
FUNCTION dosomething CDECL (BYVAL L AS lua_State PTR) AS Long
Static counter As Integer
result(counter).x=lua_tonumber(L, 1)
result(counter).y=lua_tonumber(L, 2)
counter+=1
Return 0
END Function
Sub EvaluateForAndCall(fname As String,ByVal Expression As String,StringVariable As String,DoubleVariable As Double,ByRef lua As lua_state Ptr,startx As Double,stopx As Double, stepx As Double)
Dim func As String
func = "function " + fname +"("+StringVariable+")" +Chr(13)+Chr(10) _
+ " return "+StringVariable+","+ Expression +Chr(13)+Chr(10) _
+ "end" +Chr(13)+Chr(10) _
+ "for " + StringVariable + "=" + Str(startx) + "," + Str(stopx)+ "," + Str(stepx) +" do" +Chr(13)+Chr(10) _
+ " myfunc("+fname +"("+StringVariable+"))" +Chr(13)+Chr(10) _
+ "end"
Print func
lua_pushcfunction(lua, @dosomething)
lua_setglobal(lua, "myfunc")
If luaL_dostring(Lua,func) Then
PRINT "Error: " & *lua_tostring(Lua, -1),__LINE__
sleep
EndIf
End Sub
Function Evaluate2(fname As String,ByVal Expression As String,StringVariable As String,DoubleVariable As Double,ByRef lua As lua_state Ptr) As Double
Static func As String
If Len(func)=0 Then 'setup and compile function
func = "function " + fname +"("+StringVariable+")" +Chr(13)+Chr(10) _
+ " return " + Expression +Chr(13)+Chr(10) _
+ "end"
Print func
If luaL_dostring(Lua,func) Then
PRINT "Error: " & *lua_tostring(Lua, -1),__LINE__
sleep
EndIf
EndIf
lua_getglobal(Lua, fname)
lua_pushnumber(Lua, DoubleVariable)
IF lua_pcall(Lua, 1, 1, 0) Then
Print "Error: " & *lua_tostring(Lua, -1),__LINE__
sleep
EndIf
Evaluate2 = lua_tonumber(Lua, -1)
lua_pop(Lua, 1)
End Function
Function Evaluate(ResultVariable As String,ByVal Expression As String,StringVariable As String,DoubleVariable As Double,ByRef lua As lua_state Ptr) As Double
lua_pushnumber(Lua, DoubleVariable)
lua_setglobal(Lua, StringVariable)
luaL_dostring(Lua,ResultVariable+"="+Expression)
lua_getglobal(Lua,ResultVariable)
Evaluate = lua_tonumber(Lua, -1)
lua_pop(Lua, 1)
End Function
Re: How to run a string?
RockTheSchock
To use the evaluate function, Could you not omit the function name, and just use say "f".
Also, a change in expression could cause a different function to compile, and if the expression does not change then use the previous function.
I see that there are loads of built in Lua functions, many more than vbscript.
Thank you TJF
Sorry Bob Paw, for straying off topic a bit.
To use the evaluate function, Could you not omit the function name, and just use say "f".
Also, a change in expression could cause a different function to compile, and if the expression does not change then use the previous function.
I see that there are loads of built in Lua functions, many more than vbscript.
Code: Select all
#Include Once "Lua/lua.bi"
#Include Once "Lua/lauxlib.bi"
#Include Once "Lua/lualib.bi"
Function Eval(ByVal Expression As String,StringVariable As String,DoubleVariable As Double,ByRef lua As lua_state Ptr) As Double
static as string funclast,func
'setup and compile function
if funclast<>expression then
func = "function " + "f" +"("+StringVariable+")" +Chr(13)+Chr(10) _
+ " return " + Expression +Chr(13)+Chr(10) _
+ "end"
Print func:print
If luaL_dostring(Lua,func) Then
PRINT "Error: " & *lua_tostring(Lua, -1),__LINE__
sleep
EndIf
EndIf
funclast=expression
lua_getglobal(Lua, "f")
lua_pushnumber(Lua, DoubleVariable)
IF lua_pcall(Lua, 1, 1, 0) Then
Print "Error: " & *lua_tostring(Lua, -1),__LINE__
sleep
EndIf
Eval = lua_tonumber(Lua, -1)
lua_pop(Lua, 1)
End Function
Dim Lua As lua_State Ptr = luaL_newstate :luaL_openlibs(Lua)
dim as string g="math.sin(x)"
print eval(g,"x",.5,lua)
g="x+7"
print eval(g,"x",.6,lua)
g+="+x^2"
print eval(g,"x",2,lua)
g="math.cos(x)^2 + math.sin(x)^2 +x"
for x as double=0 to 5
print eval(g,"x",x,lua)
next x
sleep
Sorry Bob Paw, for straying off topic a bit.
-
- Posts: 252
- Joined: Mar 12, 2006 16:25
Re: How to run a string?
Well the code evolved. So i just copied it. But the idea behind it was to keep track of several formula functions. Eventually one could save / load / edit them or even call another custom function from within another.
You can define for one function also a seperate environment where you include only all the math.xxx functions as local. So you dont need to type math.sin() but only sin(). Look at the sandbox link i gave.
You can define for one function also a seperate environment where you include only all the math.xxx functions as local. So you dont need to type math.sin() but only sin(). Look at the sandbox link i gave.
Re: How to run a string?
Thanks RockTheSchock.
I'll investigate the lua script library.
But it is very fast.
Here's an old plotter (previously disphelper)) converted to lua.
I have created lua (the lua_State Ptr) inside the function to save passing an extra parameter.
There are several test strings, just press a key to get each one.
I'll investigate the lua script library.
But it is very fast.
Here's an old plotter (previously disphelper)) converted to lua.
I have created lua (the lua_State Ptr) inside the function to save passing an extra parameter.
There are several test strings, just press a key to get each one.
Code: Select all
#Include Once "Lua/lua.bi"
#Include Once "Lua/lauxlib.bi"
#Include Once "Lua/lualib.bi"
Function Eval(ByVal Expression As String,StringVariable As String,DoubleVariable As Double) As Double
static as string funclast,func
static Lua As lua_State Ptr
if funclast<>expression then
lua=luaL_newstate
luaL_openlibs(Lua)
func = "function " + "f" +"("+StringVariable+")" +Chr(13)+Chr(10) _
+ " return " + Expression +Chr(13)+Chr(10) _
+ "end"
Print func:print
If luaL_dostring(Lua,func) Then
PRINT "Error: " & *lua_tostring(Lua, -1),__LINE__
sleep
EndIf
EndIf
funclast=expression
lua_getglobal(Lua, "f")
lua_pushnumber(Lua, DoubleVariable)
IF lua_pcall(Lua, 1, 1, 0) Then
Print "Error: " & *lua_tostring(Lua, -1),__LINE__
sleep
EndIf
Eval = lua_tonumber(Lua, -1)
lua_pop(Lua, 1)
End Function
'================================================================
#define map(a,b,x,c,d) ((d)-(c))*((x)-(a))/((b)-(a))+(c)
dim as integer w,h
screeninfo w,h
screenres w,h
Width ,h\16 'make the font slightly larger
dim as string fn
dim as single lx,hx,ly,hy
dim as integer xval,yval
dim as integer count
do
count=0
read fn
if fn="end" then exit do
read lx
read hx
read ly
read hy
cls
'================== the vewing box =============
line(.1*w,.1*h)-(.9*w,.9*h),,bf
draw string(.1*w,.5*h),str(lx),5
draw string(.9*w-20,.5*h),str(hx),5
draw string(.5*w,.1*h),str(hy),5
draw string(.5*w,.9*h-20),str(ly),5
draw string(.45*w,.1*h+20),fn,0
'===============================================
'plotter
for x as single=lx to hx step (hx-lx)/1000
count+=1
var value=eval(fn,"x",x)
xval=map(lx,hx,x,.1*w,.9*w)
yval=map(hy,ly,value,.1*h,.9*h)'cartesian
if count=1 then
pset(xval,yval),0
else
line -(xval,yval),0
end if
next x
sleep
loop until inkey=chr(27)
locate 2,2
print "Done"
sleep
const pi=4*atn(1)
'data function(in x),lowerX,upperX,lowerY,upperY (cartesian co-ordinates)
data "math.sin(x)",-10,10,-1.5,1.5
data "math.cos(x)",0,2*pi,-2,2
data "x^2",-5,5,0,25
data "math.sin(x)/x",-20,20,-1,2
data "3*math.sin(3*x)+2*math.cos(2*x)+math.sin(x)",-5,5,-10,10
data "(((((-2*x+5)*x)+7)*x-3)*x+9)+3",-5,5,-100,100
data "2*math.random()-2*math.random()",0,8,-2,2
data "1/math.exp(x^2)",-3,3,-1.5,1.5
data "1/(1+x^2)",-3,3,-1.5,1.5
data "end"
-
- Posts: 8586
- Joined: May 28, 2005 3:28
- Contact:
Re: How to run a string?
No one knows Squirrel V3.0 for FreeBASIC (32/64-bit Windows and Linux)
http://www.freebasic.net/forum/viewtopi ... 14&t=17573
Joshy
http://www.freebasic.net/forum/viewtopi ... 14&t=17573
Joshy
Re: How to run a string?
Code: Select all
#INCLUDE ONCE "Lua/lua.bi"
#INCLUDE ONCE "Lua/lauxlib.bi"
#INCLUDE ONCE "Lua/lualib.bi"
DIM Lua AS lua_State PTR
Lua = luaL_newstate
dim as double x = 1.01, y = 1.02, z
lua_pushnumber(Lua, 0) ' Push number on the stack
lua_setglobal(Lua, "z") ' take off the stack and assign "z"
lua_pushnumber(Lua, x) ' Push number on the stack
lua_setglobal(Lua, "x") ' take off the stack and assign "x"
lua_pushnumber(Lua, y) ' Push number on the stack
lua_setglobal(Lua, "y") ' take off the stack and assign "y"
IF luaL_dofile(Lua, "fn.lua") THEN
PRINT "Error: " & *lua_tostring(Lua, -1)
END IF
lua_getglobal(Lua, "z") ' Set value of "z" on the stack
z = lua_tonumber(Lua, 1) ' output value
? z
lua_close Lua
SLEEP
fn.lua file is just one line:
z = 2 * x + y
or more
if x>1 then x = 100 end
z = 2 * x + y