Squirrel scripting language wrapper module

BlitzMax Forums/BlitzMax Programming/Squirrel scripting language wrapper module

Well ive been floating around these forums for ages, but never posted any of my work, so i might as well now.

This is a basic wrapper for the squirrel scripting languages, if you dont know what squirrel is you can get infomation on it here - http://squirrel-lang.org/
Ive also posted some examples lower in this post.

You can download the module here - www.savefile.com/files/6495778


It now contains a few examples to show things like precompilations and parameter masking, it also contains a type called TSquirrelEngine to make using squirrel a LOT easier, as it handles all the complex stack routines for you. Theres still a lot of things to implement though such as classes, arrays and such, but there coming along :).

Anyway enjoy, hope thats helpfull.

BlitzMax Code:
Rem

	Squirrel - Example 4 : Precompiling
	This shows how to precompile a script
	
	Created by Tim Leonard (Aka. Helios)
	Version 1.0

End Rem

Rem
	Framework
End Rem
Strict
Framework BRL.System
	Import BRL.retro
	Import DE.Squirrel
	
Rem
	Squirrel Example
End Rem

' Create a new squirrelengine
Global SE:TSquirrelEngine = New TSquirrelEngine

' Load the test file 
SE.LoadFile("Scripts\Example4.nut")

' Now lets dump the compile bytecode to a file
SE.DumpByteCode("Scripts\Example4.cnut")

' Kill Old Squirrel Engine
SE = Null
FlushMem()

' Now to show that this has dumped the file
' succcesfully, we will create another squirrel engine
' and make it run it

' Create new engine
SE:TSquirrelEngine = New TSquirrelEngine

' Register a simple function with
' a parameter mask and count
SE.RegisterGlobalFunction(func_Notify,"Notify",2,"sn")

' Now lets test if it reads out byte code 
' successfully, it will auromatically decide
' if the file is compiled or not and load it 
' appropriatly, you shhould notice a loading dip of about
' 10ms for a simple script when you precompile
SE.LoadFile("Scripts\Example4.cnut")
Se.Run()

Rem
	Our squirrel function, must always 
	have the prototype of FunctionName(State:Byte ptr)
	
	This is called with 2 paremeters the first being a string
	and the second being a integer
End Rem
Function Func_Notify(State:Byte Ptr)

	' Please not that when accessing paremeters 
	' always start at 0 as the TSquirrelEngine access 
	' them as zero-based
	Notify SE.GetStringParameter(0),SE.GetIntegerParameter(1)

End Function


Squirrel Code:
local table = {
	a = "10"
	subtable = {
		array = [1,2,3]
	},
	[10 + 123] = "expression index"
}

local array=[ 1, 2, 3, { a = 10, b = "string" } ];

foreach (i,val in array)
{
	::print("the type of val is"+typeof val);
}

/////////////////////////////////////////////


class Entity
{	
	constructor(etype,entityname)
	{
		name = entityname;
		type = etype;
	}
									
	x = 0;
	y = 0;
	z = 0;
	name = null;
	type = null;
}

function Entity::MoveTo(newx,newy,newz)
{
	x = newx;
	y = newy;
	z = newz;
}

class Player extends Entity {
	constructor(entityname)
	{
		Entity.constructor("Player",entityname)
	}
	function DoDomething()
	{
		::print("something");
	}
	
}


local newplayer = Player("da playar");

newplayer.MoveTo(100,200,300);	


cool, I really like Squirrel

It's like LUA ?


It's like LUA ?


Feature wise yes, syntax wise no.

Ok ! Good job :)

aaauug, curly braces! hiss! boo! It looks a lot like C.

Hum, can someone help me with something? I trying to get function parameters from the stack with sq_getstring but i always seem to get a nullexception error, and i cant work out how to get it to work. Heres another download - http://www.nexuschat.com/uploader/uploads/SquirrelModule_v2.zip
That contains the new TSquirrelEngine type and an examples folder, the example in that shows the error that happens, if anyone could help it would be greatly appreciated :).

EDIT: nvm, found the problem, just need a couple of var's added to the function declarations.

Released a more updated version.

You can get it here
www.nexuschat.com/uploader/uploads/SquirrelModule_v2.zip

It now contains a few examples to show things like precompilations and parameter masking, it also contains a type called TSquirrelEngine to make using squirrel a LOT easier, as it handles all the complex stack routines for you. Theres still a lot of things to implement though such as classes, arrays and such, but there coming along , and so far most of what is in lua is now implemented, its just squirrel specific that needs doing. Its also fixed a lot of bugs and redesigned a lot of things from Version 1.

~ Enjoy

Hi, I want use your library in my game, but I have a little problem.
How can I modify a Blitzmax variable or object from a Squirrel program?
I think calling Blitzmax functions from Squirrel is one way, but there are any more ways?
Thx, i like this module a lot

Do you mean like a Set/GetGlobal command or as in using pointers in your script to directly modify something?

Using pointers in my script to directly modify something. It's possible?

Well you can pass pointers(or userdata as its known) into squirrel, but you would need some functions to modify them as as far as i know userdata is read-only.
But if you want get/setglobal functions, you will have to wait a bit, ive so far worked out how to set globals, but i cant for the life of me work out how to get them.

looks good... I'll have to take a look at this and squirrel.

Got an error while building the module for 1.14 in OSX 10.3.9:
Compile Error: Unable to convert from 'String' to 'Byte Ptr'
[/Applications/BlitzMax/mod/de.mod/squirrel.mod/squirrel.bmx;380;3]
Build Error: failed to compile /Applications/BlitzMax/mod/de.mod/squirrel.mod/squirrel.bmx


Edit:

This change compiled, but don't know if it leaks memory or works at all. :)
	Rem
		bbdoc: Used to load and compile a string 
	End Rem
	Method LoadString(Buffer:String,SourceName:String)
		Local bptr:Byte Ptr = buffer.ToCString()
		Local sptr:Byte Ptr = sourcename.ToCString()
		'Return sq_compilebuffer(State,Buffer.ToCString(),Len(Buffer),SourceName,1)
		Local Ret:Int = sq_compilebuffer(State,bptr,Len(Buffer),sptr,1)
		MemFree bptr
		MemFree sptr
		Return ret
	End Method


yet another edit:
Not sure if it is related to the above fix (But I guess it is)
All examples compiles just fine and doesn't crash. But nothing happends when I run them. :P

last edit:
...And that's because a path in a sane operating system uses forward slashes. Everything seemes to work just fine now if I change every \ to / in the examples.

wow! Nice. This looks better than LUA I must say.

Believe it or not, part of it is based on Lua.

Well not really. It's totally different code. Sure it exposes a stack to the embedder (like other script engines), but otherwise the code is completely different. It may have been *inspired* by LUA, but they don't share code.

One nice thing is that you can easily alter the lexer to create new keywords, and change the syntax around... nice.

BTW Helios... what happened to your module? Can you upload it again?

Cheers!

Give me a second, just got to re-upload it, i changed the domain of my site ;D.

It may have been *inspired* by LUA, but they don't share code.


Nope, its table code is based on Lua's. They state it clearly on the front page of their site.

Squirrel is based on Lua, but internally only. Syntax is very different (better in my opinion)

My bad then... I didn't look at the table code.

*Smack*

So. Where could I download the module again?

Sorry I had to reformat my pc a couple of days ago so minGW isn't installed so I was unable to compile it, you'll have to do it yourself, so I cant be sure theres no bugs in it. My website is also having probs so ive had to upload it to a free file hoster.

Download it here - http://www.savefile.com/files/6429950

i get complie error cause you used superstrict and didn't give some consts a var type (%). just tho i say this if anyone else was getting this problem. gj btw :D

edit: also i couldnt find a list called EngineList.

edit2: i think it needs to be called list instead

edit3: I think you need to change the error bit as well cause its a function:
If T.State = State
				TSquirrelEngine.ErrorDescription = Description
				TSquirrelEngine.ErrorSourcename  = SourceName
				TSquirrelEngine.ErrorLine		 = Line
				TSquirrelEngine.ErrorColumn		 = Column
			EndIf


edit4: You need to change the def of the above vars aswell to be global instead.

NOTE I dont know if this is how you should fix it but after the doing what i said above the module complied (i dont know if other things (internally) will get effected)

edit5: you need to change the examples as well to binphx instead of de.

thats not too much :D

Whoops, sorry, told you it probably had bugs in it. Heres a *hopefully* fixed one.

http://www.savefile.com/files/6495778

for some stange reson example 3 doesnt do anything.

edit1: example four does somthing but i dont think GetGlobalString() is working correctly because it doesntprint anything out.

>_<, sorry another problem, that was caused by me testing the global variable code, i forgot to remove it, but it should work fine if you remove the GetGlobal asn SetGlobal lines from example 3 & 4. I apologise for all this when i get mingwa installed and sorted out ill fix it up and release it properly.

kool, at lest your showing your still working on it :D

Excellent... thank you Helios.... Hey Mark... I think this might be one for the public modules.

so how goes this - the download is no longer on save file :(

File ID is not valid



so how goes this


Not working on it at the moment, been creating my own scripting language :) (Which is going awesome, almost fully functional at the moment, and pretty fast.)


- the download is no longer on save file :(


Yeh im sorry, SaveFile.com auto deletes the files if there not downloaded for n amount of time.

Ill upload it again if you want it back up.

Ill upload it again if you want it back up.

not for me, i have a copy.

Not working on it at the moment, been creating my own scripting language :) (Which is going awesome, almost fully functional at the moment, and pretty fast.)
cool!!! look forwed to seeing it.

Hey does anyone still have a copy of this module?? Can someone post a link to it?

Well, I don't have this module, but here's the source to my Squirrel module (haven't released it since I figured nobody would care with the existence of Lua).

SuperStrict

Module Cower.Squirrel

Import "sqapi.cpp"
Import "sqbaselib.cpp"
Import "sqclass.cpp"
Import "sqcompiler.cpp"
Import "sqdebug.cpp"
Import "sqfuncstate.cpp"
Import "sqlexer.cpp"
Import "sqmem.cpp"
Import "sqobject.cpp"
Import "sqstate.cpp"
Import "sqstdaux.cpp"
Import "sqstdmath.cpp"
Import "sqstdrex.c"
Import "sqstdstring.cpp"
Import "sqtable.cpp"
Import "sqvm.cpp"

Const _RT_NULL%=$00000001
Const _RT_INTEGER%=$00000002
Const _RT_FLOAT%=$00000004
Const _RT_BOOL%=$00000008
Const _RT_STRING%=$00000010
Const _RT_TABLE%=$00000020
Const _RT_ARRAY%=$00000040
Const _RT_USERDATA%=$00000080
Const _RT_CLOSURE%=$00000100
Const _RT_NATIVECLOSURE%=$00000200
Const _RT_GENERATOR%=$00000400
Const _RT_USERPOINTER%=$00000800
Const _RT_THREAD%=$00001000
Const _RT_FUNCPROTO%=$00002000
Const _RT_CLASS%=$00004000
Const _RT_INSTANCE%=$00008000
Const _RT_WEAKREF%=$00010000
Const SQOBJECT_REF_COUNTED%=$08000000
Const SQOBJECT_NUMERIC%=$04000000
Const SQOBJECT_DELEGABLE%=$02000000
Const SQOBJECT_CANBEFALSE%=$01000000
Const SQ_MATCHTYPEMASKSTRING%=(-99999)
Const SQ_VMSTATE_IDLE%=0
Const SQ_VMSTATE_RUNNING%=1
Const SQ_VMSTATE_SUSPENDED%=2
Const SQUIRREL_EOB%=0
Const SQ_BYTECODE_STREAM_TAG%=$FAFA

Const OT_NULL%=_RT_NULL|SQOBJECT_CANBEFALSE
Const OT_INTEGER%=_RT_INTEGER|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE
Const OT_FLOAT%=_RT_FLOAT|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE
Const OT_BOOL%=_RT_BOOL|SQOBJECT_CANBEFALSE
Const OT_STRING%=_RT_STRING|SQOBJECT_REF_COUNTED
Const OT_TABLE%=_RT_TABLE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE
Const OT_ARRAY%=_RT_ARRAY|SQOBJECT_REF_COUNTED
Const OT_USERDATA%=_RT_USERDATA|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE
Const OT_CLOSURE%=_RT_CLOSURE|SQOBJECT_REF_COUNTED
Const OT_NATIVECLOSURE%=_RT_NATIVECLOSURE|SQOBJECT_REF_COUNTED
Const OT_GENERATOR%=_RT_GENERATOR|SQOBJECT_REF_COUNTED
Const OT_USERPOINTER%=_RT_USERPOINTER
Const OT_THREAD%=_RT_THREAD|SQOBJECT_REF_COUNTED
Const OT_CLASS%=_RT_CLASS|SQOBJECT_REF_COUNTED
Const OT_INSTANCE%=_RT_INSTANCE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE
Const OT_WEAKREF%=_RT_WEAKREF|SQOBJECT_REF_COUNTED

Extern "C"
Function sq_open:Byte Ptr(initialstacksize:Int)
Function sq_newthread:Byte Ptr(friendvm:Byte Ptr, initialstacksize:Int)
Function sq_seterrorhandler(v:Byte Ptr)
Function sq_close(v:Byte Ptr)
Function sq_setforeignptr(v:Byte Ptr, p:Byte Ptr)
Function sq_getforeignptr:Byte Ptr(v:Byte Ptr)
Function sq_setprintfunc(v:Byte Ptr, printfunc:Byte Ptr)
Function sq_getprintfunc:Byte Ptr(v:Byte Ptr)
Function sq_suspendvm:Int(v:Byte Ptr)
Function sq_wakeupvm:Int(v:Byte Ptr, resumedret:Int, retval:Int)
Function sq_getvmstate:Int(v:Byte Ptr)
Function sq_compile:Int(v:Byte Ptr, read:Byte Ptr, p:Byte Ptr, sourcename$z, raiseerror:Int)
Function sq_compilebuffer:Int(v:Byte Ptr, s$z, size:Int, sourcename$z, raiseerror:Int)
Function sq_enabledebuginfo(v:Byte Ptr, debuginfo:Int)
Function sq_setcompilererrorhandler(v:Byte Ptr, f:Byte Ptr)
Function sq_push(v:Byte Ptr, idx:Int)
Function sq_pop(v:Byte Ptr, nelemstopop:Int)
Function sq_poptop(v:Byte Ptr)
Function sq_remove(v:Byte Ptr, idx:Int)
Function sq_gettop:Int(v:Byte Ptr)
Function sq_settop(v:Byte Ptr, newtop:Int)
Function sq_reservestack(v:Byte Ptr, nsize:Int)
Function sq_cmp:Int(v:Byte Ptr)
Function sq_move(dest:Byte Ptr, src:Byte Ptr, idx:Int)
Function sq_newuserdata:Byte Ptr(v:Byte Ptr, size:Int)
Function sq_newtable(v:Byte Ptr)
Function sq_newarray(v:Byte Ptr, size:Int)
Function sq_newclosure(v:Byte Ptr, func:Byte Ptr, nfreevars:Int)
Function sq_setparamscheck:Int(v:Byte Ptr, nparamscheck:Int, typemask$z)
Function sq_pushstring(v:Byte Ptr, s$z, length:Int)
Function sq_pushfloat(v:Byte Ptr, f:Float)
Function sq_pushinteger(v:Byte Ptr, n:Int)
Function sq_pushbool(v:Byte Ptr, b:Int)
Function sq_pushuserpointer(v:Byte Ptr, p:Byte Ptr)
Function sq_pushnull(v:Byte Ptr)
Function sq_gettype:Int(v:Byte Ptr, idx:Int)
Function sq_getsize:Int(v:Byte Ptr, idx:Int)
Function sq_tostring(v:Byte Ptr, idx:Int)
Function sq_getstring:Int(v:Byte Ptr, idx:Int, c:Byte Ptr Var)
Function sq_getinteger:Int(v:Byte Ptr, idx:Int, i:Int Var)
Function sq_getfloat:Int(v:Byte Ptr, idx:Int, f:Float Var)
Function sq_getbool:Int(v:Byte Ptr, idx:Int, b:Int Var)
Function sq_getthread:Int(v:Byte Ptr, idx:Int, thread:Byte Ptr Var)
Function sq_getuserpointer:Int(v:Byte Ptr, idx:Int, p:Byte Ptr Var)
Function sq_getuserdata:Int(v:Byte Ptr, idx:Int, p:Byte Ptr Var, typetag:Byte Ptr Var)
Function sq_settypetag:Int(v:Byte Ptr, idx:Int, typetag:Byte Ptr Var)
Function sq_gettypetag:Int(v:Byte Ptr, idx:Int, typetag:Byte Ptr VAr)
Function sq_setreleasehook(v:Byte Ptr, idx:Int, hook:Byte Ptr)
Function sq_getscratchpad$z(v:Byte Ptr, minsize:Int)
Function sq_getclosureinfo:Int(v:Byte Ptr, idx:Int, nparams:Byte Ptr, nfreevars:Byte Ptr)
Function sq_setnativeclosurename:Int(v:Byte Ptr, idx:Int, name$z)
Function sq_setinstanceup:Int(v:Byte Ptr, idx:Int, p:Byte Ptr)
Function sq_getinstanceup:Int(v:Byte Ptr, idx:Int, p:Byte Ptr, typetag:Byte Ptr)
Function sq_newclass:Int(v:Byte Ptr, hasbase:Int)
Function sq_createinstance:Int(v:Byte Ptr, idx:Int)
Function sq_setattributes:Int(v:Byte Ptr, idx:Int)
Function sq_getattributes:Int(v:Byte Ptr, idx:Int)
Function sq_getclass:Int(v:Byte Ptr, idx:Int)
Function sq_weakref(v:Byte Ptr, idx:Int)
Function sq_pushroottable(v:Byte Ptr)
Function sq_pushregistrytable(v:Byte Ptr)
Function sq_setroottable:Int(v:Byte Ptr)
Function sq_createslot:Int(v:Byte Ptr, idx:Int)
Function sq_deleteslot:Int(v:Byte Ptr, idx:Int, pushval:Int)
Function sq_set:Int(v:Byte Ptr, idx:Int)
Function sq_get:Int(v:Byte Ptr, idx:Int)
Function sq_rawget:Int(v:Byte Ptr, idx:Int)
Function sq_rawset:Int(v:Byte Ptr, idx:Int)
Function sq_rawdeleteslot:Int(v:Byte Ptr, idx:Int, pushval:Int)
Function sq_arrayappend:Int(v:Byte Ptr, idx:Int)
Function sq_arraypop:Int(v:Byte Ptr, idx:Int, pushval:Int)
Function sq_arrayresize:Int(v:Byte Ptr, idx:Int, newsize:Int)
Function sq_arrayreverse:Int(v:Byte Ptr, idx:Int)
Function sq_setdelegate:Int(v:Byte Ptr, idx:Int)
Function sq_getdelegate:Int(v:Byte Ptr, idx:Int)
Function sq_clone:Int(v:Byte Ptr, idx:Int)
Function sq_setfreevariable:Int(v:Byte Ptr, idx:Int, nval:Int)
Function sq_next:Int(v:Byte Ptr, idx:Int)
Function sq_getweakrefval:Int(v:Byte Ptr, idx:Int)
Function sq_call:Int(v:Byte Ptr, params:Int, retval:Int)
Function sq_resume:Int(v:Byte Ptr, retval:Int)
Function sq_getlocal$z(v:Byte Ptr, level:Int, idx:Int)
Function sq_getfreevariable$z(v:Byte Ptr, idx:Int, nval:Int)
Function sq_throwerror:Int(v:Byte Ptr, err$z)
Function sq_reseterror(v:Byte Ptr)
Function sq_getlasterror(v:Byte Ptr)
Function sq_getstackobj:Int(v:Byte Ptr, idx:Int, po:Byte Ptr)
Function sq_pushobject(v:Byte Ptr, obj:Byte Ptr)
Function sq_addref(v:Byte Ptr, po:Byte Ptr)
Function sq_release:Int(v:Byte Ptr, po:Byte Ptr)
Function sq_resetobject(po:Byte Ptr)
Function sq_objtostring$z(o:Byte Ptr)
Function sq_objtobool:Int(o:Byte Ptr)
Function sq_objtointeger:Int(o:Byte Ptr)
Function sq_objtofloat:Float(o:Byte Ptr)
Function sq_collectgarbage:Int(v:Byte Ptr)
Function sq_writeclosure:Int(vm:Byte Ptr, writef:Byte Ptr, up:Byte Ptr)
Function sq_readclosure:Int(vm:Byte Ptr, readf:Byte Ptr, up:Byte Ptr)
Function sq_malloc:Byte Ptr(size:Int)
Function sq_realloc:Byte Ptr(p:Byte Ptr, oldsize:Int, newsize:Int)
Function sq_free(p:Byte Ptr, size:Int)
Function sq_stackinfos:Int(v:Byte Ptr, level:Int, si:Byte Ptr)
Function sq_setdebughook(v:Byte Ptr)
Function sqstd_rex_compile:Byte Ptr(pattern$z, error:Byte Ptr)
Function sqstd_rex_free(exp:Byte Ptr)
Function sqstd_rex_match:Int(exp:Byte Ptr, text$z)
Function sqstd_rex_search:Int(exp:Byte Ptr, text$z, out_begin:Byte Ptr, out_end:Byte Ptr)
Function sqstd_rex_searchrange:Int(exp:Byte Ptr, text_begin$z, text_end$z, out_begin:Byte Ptr, out_end:Byte Ptr)
Function sqstd_rex_getsubexpcount:Int(exp:Byte Ptr)
Function sqstd_rex_getsubexp:Int(exp:Byte Ptr, n:Int, subexp:Byte Ptr)
Function sqstd_register_stringlib:Int(v:Byte Ptr)
Function sqstd_seterrorhandlers(v:Byte Ptr)
Function sqstd_printcallstack(v:Byte Ptr)
End Extern

Function SQ_SUCCEEDED%( v:Int )
    Return (v >= 0)
End Function
Function SQ_FAILED%( v:Int )
    Return (v < 0)
End Function


I was about to write my own module, but now I don't have to. Thanks fellas.

Oh nice Noel... thanks for that. Does the string stuff function correctly?

Has anyone tested squirrel on Mac? PPC?

I haven't tested it thoroughly yet as I decided not to use it for my project, so I'm afraid I can't say whether or not it works on a Mac or if the string implementation works.