json basic scripting language [update 7/18]

User projects written in or related to FreeBASIC.
rolliebollocks
Posts: 2655
Joined: Aug 28, 2008 10:54
Location: new york

json basic scripting language [update 7/18]

Post by rolliebollocks »

The code is below. I wanted to write a new scripting language and I wanted the base variable to be a JSON object. Although it is currently a work in progress I though maybe others might be interested in the project. And of course, anyone willing to give it a run and test it out would be handsomely rewarded with a thank you click.

!! UPDATE (7.18) !!

Sourceforge has been updated. Board pastes will be updated later. Tired now. Passing functions with parameters is buggy, without parameters should work properly. This is the last known bug.

Download:
https://sourceforge.net/projects/infini ... p/download

#ADDED#

Variables of JSON type
Basic Math Operators and Functions
Basic String Operators and Functions
Assignment Operators
Comparison operators ( ==, <=, >=, <, >, !=, <> )
Conditional statements (if,else)
Array/String Operator Pluck myArray[ index ]
for loop
while loop
myArray[ index ] = value
objects
object[ key ]
object.key
object[ key ] = someValue
object.key = someValue
array.push_back( someValue )
array.pop( index )
array.push( index, someValue )
array.left( index )
array.right( index )
array.mid( index, length )
array.slice( index1, index2 )
array.first
array.last
array.length
len(array) still works
string.split( delimiters, array )
split( string, delimiters, array )
string.slice( index1, index2 )
slice( string, index1, index2 )
string.length
select & case
bitwise && and || or if you please and and or
typeof( variable )
Scoping implemented for functions, if, for, and while
array.clear

#NEW#

Dynamic Scoping:

Keep in mind: Firstly, any variable declared in the implicit main scope is considered shared. It is part of variables.vars[0] (from the context) which can never be popped from the vector. Secondly, all bracketed expressions now create their own scope. You must close them off with an end line. Bracketed expressions are treated like a single line and run the through parser together. Scope is popped immediately after the bracket is closed, and that information is lost. Non-variable expressions are printed as strings. So when the scope containing 'y' is popped it simply prints 'y'.

Code: Select all

var x = 10;

{
	print( x );
	var y = 20;
	print( y );
};

print( x );
print( y );
Self-Parsing Functions

Code: Select all

var s = load_file_as_string( "Examples/array.jsb" );
parse( s );
There is hardly anything to bear in mind about this. It simply calls the same function JSB uses to parse any script. You can also call the Evaluator which is for single lines or sub-lines. So for instance you can dereference a variable using eval. Much testing must be done. But something like this works:

Code: Select all

var s = "beep;";
eval( s );
Var Len Arg Functions

So, if you're interested in adding your own functions to JSB, you really do not have to specify a signature anymore. You can follow the instructions further down this thread to add your own function. As a standard, I use "%f(%a,...)" as a signature. JSB can count how many parameters there are in a function pass and build the arguments and pass them automatically.

Now I need a break. There may be some glitches. If you run into anything, lemme know. Thx.

#TO ADD#

grammar
test suite
Lots of other stuff

^WORTH NOTING^

#1. I have a lot of tests to run.
#2. I have a lot of debugging to do
#3. I have some optimizing to do
#4. I don't know what I'm doing
#5. The parser is mostly recursive calls to itself
#6. The parser is a lot of macros
#7. The code is mostly unreadable ( sorry )
Last edited by rolliebollocks on Jul 18, 2014 5:25, edited 31 times in total.
rolliebollocks
Posts: 2655
Joined: Aug 28, 2008 10:54
Location: new york

Re: json basic scripting language

Post by rolliebollocks »

parsing.bas

Code: Select all

function IsWhite( byval c as ubyte ) as integer
  if c=32 then return 1
  if c= 9 then return 1
  if c=10 then return 1
  if c=13 then return 1
  return 0
end function

function Is_Alpha( byval c as ubyte ) as integer
  select case as const c
  case asc("a") to asc("z") : return 1
  case asc("A") to asc("Z") : return 1
  case asc("_"), asc("-") : return 1
  end select
  return 0
end function

function IsNumberJson( byval c as ubyte ) as integer
  select case as const c
  case asc("0") to asc("9") : return 1
  case asc("-"), asc(".") : return 1
  end select
  return 0
end function

function IsAlphaNum( byval c as ubyte ) as integer
  If Is_Alpha(c) then return 1
  If IsNumberJson(c) then return 1
  return 0
end function

dim shared as string*1 ASCII(255)

for i as integer = 0 to 255 : ASCII(i) = chr(i) : next i
    
Function LoadFileAsString( Byref filename As String ) As String

        Dim x As String

        If( Open( filename For Input Access Read As #13 ) = 0 ) Then
                Close #13
                If( Open( filename For Binary Access Read As #13 ) = 0 ) Then
                        x = Space( Lof( 13 ))
                        Get #13,,x
                        Close #13
                Else
                        print "Unable to open '" & filename & "'"
                End If 
        Else
        print "File not found '" & filename & "'"
        End If

        Function = x

End Function

function unEscape( byval s as string ) as string
    dim as string res = ""
    dim as integer i = 0
    dim as integer l = len( s ) - 1
    
    Do
        if s[i] = asc("\") andalso i < l then
            select case s[i+1]
            case 34  : res += ascii( 34 ) : i += 1
            case asc("/") : res += "/" : i += 1
            case asc("\") : res += "\" : i += 1
            case asc("b") : res += ascii( 8 ) : i += 1
            case asc("f") : res += ascii( 12 ) : i += 1
            case asc("n") : res += !"\n" : i += 1
            case asc("r") : res += !"\r" : i += 1
            case asc("t") : res += !"\t" : i += 1
            'case asc("u") : res += ascii( s[i] ) : i += 2
            case else : res += ascii( s[i] ) : i += 1
            end select
        else
            res += ascii( s[i] )
        endif
        
        i += 1
        if i > l then exit do
    loop
    return res
end function
Last edited by rolliebollocks on Jul 10, 2014 2:17, edited 1 time in total.
rolliebollocks
Posts: 2655
Joined: Aug 28, 2008 10:54
Location: new york

Re: json basic scripting language

Post by rolliebollocks »

vector.bi

Code: Select all

#include once "crt.bi"

#If __FB_VERSION__ < "0.91.0"
    #Error FB Version 0.91 or higher needed!
#EndIf

#ifndef NULL
#define NULL 0
#endif

#macro initVector(_MYTYPE_)
type vector##_MYTYPE_
    dim as integer      size
    dim as _MYTYPE_     array(any)
   
    declare Constructor()
    declare Destructor()
    declare Constructor( byref rhs as vector##_MYTYPE_ )
    declare Operator Let( byref rhs as vector##_MYTYPE_ )
    declare Operator [] ( byval index as integer ) byref as _MYTYPE_
       
    declare function begin() as _MYTYPE_ ptr  
    declare function back() as _MYTYPE_ ptr
    declare function at( byval idx as integer ) as _MYTYPE_ ptr
    declare sub      clear()
    declare function data() as _MYTYPE_ ptr
    declare function empty() as integer  
   
    declare sub push_back( byref element as _MYTYPE_ )
    declare sub insert( byval idx as integer, byref element as _MYTYPE_ )    
    declare sub pop_back()
    declare sub resize( byval n as integer )
    declare sub pop( byval n as integer )
end type

Constructor vector##_MYTYPE_ ()
end Constructor

Destructor vector##_MYTYPE_ ()
end destructor

Constructor vector##_MYTYPE_( byref rhs as vector##_MYTYPE_ )
    this.size = rhs.size
    dim as integer lb = lbound(rhs.array)
    dim as integer ub = ubound(rhs.array)
    redim this.array( lb to ub )
    for i as integer = lb to ub
        this.array(i) = rhs.array(i)
    next i
end Constructor

Operator vector##_MYTYPE_.Let( byref rhs as vector##_MYTYPE_ )
    if @this = @rhs then exit Operator
    this.size = rhs.size
    dim as integer lb = lbound(rhs.array)
    dim as integer ub = ubound(rhs.array)
    redim this.array( lb to ub )
    for i as integer = lb to ub
        this.array(i) = rhs.array(i)
    next i
end Operator

Operator vector##_MYTYPE_.[] ( byval index as integer ) byref as _MYTYPE_
    return array( index )
end Operator

function vector##_MYTYPE_.begin() as _MYTYPE_ ptr
    if this.size = 0 then return NULL
    return @array( lbound(array) )
end function

function vector##_MYTYPE_.back() as _MYTYPE_ ptr
    if this.size = 0 then return NULL
    return @array( ubound(array) )
end function

function vector##_MYTYPE_.at( byval idx as integer ) as _MYTYPE_ ptr
    if idx < lbound(array) then return NULL
    if idx > ubound(array) then return NULL
    return @array(idx)
end function

function vector##_MYTYPE_.data() as _MYTYPE_ ptr
    return @array( lbound(array) )
end function

function vector##_MYTYPE_.empty() as integer
    if size then return 0
    return -1
end function

sub vector##_MYTYPE_.push_back( byref element as _MYTYPE_ )
    dim as integer ub = ubound(array)
    redim preserve array( lbound(array) to ub+1 )
    array(ub+1) = element
    size += 1    
end sub

sub vector##_MYTYPE_.insert( byval idx as integer, byref element as _MYTYPE_ )
    dim as integer lb = lbound(array)
    dim as integer ub = ubound(array)
    if idx > ub then exit sub
    if idx < lb then exit sub
    size += 1
   
    redim preserve array( lb to ub+1 )
   
    for i as integer = ub to idx step -1
        swap this.array(i), this.array(i+1)
    next i
    this.array(idx) = element
end sub

sub vector##_MYTYPE_.pop_back()
    size -= 1
    dim as integer lb = lbound(array)
    dim as integer ub = ubound(array)
    
    redim preserve array( lb to ub-1 )
end sub

sub vector##_MYTYPE_.clear()
    erase( array )
    size = 0
end sub

sub vector##_MYTYPE_.resize( byval n as integer )
    dim as integer lb = lbound(array)
    redim preserve array( lb to lb+n-1 )
    size = n
end sub

sub vector##_MYTYPE_.pop( byval idx as integer )
    dim as integer lb = lbound(array)
    dim as integer ub = ubound(array)
   
    if idx < lb or idx > ub then exit sub
    if size = 1 then erase( array ) : size = 0: exit sub
   
    for i as integer = idx+1 to ub
        array(i-1) = array(i)
    next
   
    size -= 1
    redim preserve array( lb to ub-1 )        
end sub
#endMacro

Last edited by rolliebollocks on Jul 04, 2014 21:31, edited 3 times in total.
rolliebollocks
Posts: 2655
Joined: Aug 28, 2008 10:54
Location: new york

Re: json basic scripting language

Post by rolliebollocks »

json_parser.bas

Code: Select all

#include once "parsing.bas"

#ifndef NULL
#define NULL 0
#endif

#DEFINE DBLQUOTE ascii(34)

enum varType
  _MALFORMED_ = 0
  _NUMBER_    = 1
  _STRING_    = 2
  _BOOL_      = 3
  _ARRAY_     = 4
  _OBJECT_    = 5
  _NULL_      = 6
end enum

enum JSON_BOOL
    _FALSE_ = 0
    _TRUE_  = 1
end enum

type variable_ as variable

type varArray
    
    Public: 
    
        declare Destructor()
        declare sub add( byval item as variable_ ptr )
        declare function get( byval index as integer ) as variable_ ptr
        declare function getLength() as integer
        declare sub push( byval idx as integer, byval item as variable_ ptr )
        declare sub push( byval idx as integer, byref item as variable_ )
        declare sub pop( byval item as integer )
        declare sub push_back( byval item as variable_ ptr )
        declare sub clear()
            
        as integer size
        as variable_ ptr items(any)
        
end type

type varObjectField
    as string           key 
    as variable_ ptr    value
end type

type varObject

    Public:
    
        declare Destructor()
        declare sub add( byval key as string, byval item as variable_ ptr )
        declare function get( byval key as string ) as variable_ ptr
        declare function getKey( byval index as integer ) as string
        declare function getValue( byval index as integer ) as variable_ ptr
        declare function getSize() as integer
           
        as integer              size
        as varObjectField ptr   fields(any)

end type

type variable

    Public:
        declare Constructor()
        declare Constructor( byval json as string, byval n as string = "" )
        declare Constructor( byval n as double )
        declare Destructor()
        declare Operator Let( byval json as string )
        declare Operator Let( byval n as double )
        
        declare sub         init( byval s as string, byval n as string = "" )
        
        declare function    getType() as string
        declare function    getTypeNum() as vartype
        declare function    toString() as string
      
        declare function    getNumber() as double
        declare function    getString() as string
        declare function    getBoolean() as integer
        declare function    getArray() as vararray ptr
        declare function    getObject() as varobject ptr

        as string           lbl
        as varType          typ
        as double           number
        as string           strng
        as integer          bool
        as varArray ptr     array
        as varObject ptr    object

end type

Destructor varArray()
    for i as integer = 0 to this.size-1
        delete items(i)
    next
End Destructor

sub varArray.add( byval item as variable_ ptr )
    size += 1
    redim preserve items(size-1)
    items(size-1) = new variable_
    *items(size-1) = *item
end sub

sub varArray.push( byval idx as integer, byval item as variable_ ptr )
    if idx < 0 then exit sub
    if idx > size-1 then exit sub
    
    redim preserve items( size )
    items( size ) = new variable_
    
    for i as integer = size-1 to idx step -1
        swap items(i), items(i+1)
    next i
    
    *items( idx ) = *item
    
    size += 1
end sub

sub varArray.push( byval idx as integer, byref item as variable_ )
    if idx < 0 then exit sub
    if idx > size-1 then exit sub
    
    redim preserve items( size )
    
    for i as integer = size-1 to idx step -1
        swap items(i), items(i+1)
    next i
    
    *items( idx ) = item
    
    size += 1
end sub

sub varArray.push_back( byval item as variable_ ptr )    
    redim preserve items( size )
    items( size ) = new variable_
    *items( size ) = *item
    size += 1
end sub

sub varArray.pop( byval idx as integer )
    if idx < 0 then exit sub
    if idx > size-1 then exit sub
    if size = 1 then 
        erase( items )
        size = 0
        exit sub
    endif
    
    for i as integer = idx+1 to size-1
        items(i-1) = items(i)
    next
   
    size -= 1
    redim preserve items( 0 to size-1 )        
end sub

sub varArray.clear()
    for i as integer = 0 to size-1
        delete items(i)
    next i
    erase items
    size = 0
end sub

function varArray.get( byval index as integer ) as variable_ ptr
    if index >= size or index < 0 then return NULL
    return items(index)
end function

function varArray.getLength() as integer
    return size
end function

Destructor varObject
    for i as integer = 0 to this.size-1
        delete fields(i)
    next i
end Destructor

sub varObject.add( byval key as string, byval item as variable_ ptr )
    size += 1
    redim preserve fields(size-1)
    fields(size-1) = new varObjectField
    fields(size-1)->key = key
    fields(size-1)->value = new variable
    *fields(size-1)->value = *item
end sub

function varObject.get( byval key as string ) as variable_ ptr
    key = chr(34)+key+chr(34)
    for i as integer = 0 to size-1
        if fields(i)->key = key then return fields(i)->value
    next i
    return 0
end function

function varObject.getKey( byval index as integer ) as string
    return fields(index)->key
end function

function varObject.getValue( byval index as integer ) as variable_ ptr
    return fields(index)->value
end function

function varObject.getSize() as integer
    return size
end function

declare Operator = ( byref lhs as variable, byref rhs as variable ) as integer

Constructor variable()
end Constructor

Constructor variable( byval json as string, byval n as string = "" )
    init( json, n )
end Constructor

Constructor variable( byval num as double )
    this.typ = _NUMBER_
    this.number = num
end Constructor

Operator variable.Let( byval json as string )
    init( json )
end Operator

Operator variable.Let( byval num as double )
    this.typ = _NUMBER_
    this.number = num
end Operator

Operator = ( byref lhs as varObjectField, byref rhs as varObjectField ) as integer
    if lhs.key <> rhs.key then return 0
    if ( *lhs.value = *rhs.value ) = 0 then return 0
    return -1
end Operator

Operator = ( byref lhs as variable, byref rhs as variable ) as integer
    if lhs.typ <> rhs.typ then return 0
    select case lhs.typ
    case varType._NUMBER_
        if lhs.number <> rhs.number then return 0
    case varType._STRING_
        if lhs.strng <> rhs.strng then return 0
    case varType._BOOL_
        if lhs.bool <> rhs.bool then return 0
    case varType._ARRAY_
        if lhs.array->size <> rhs.array->size then return 0
        for i as integer = 0 to lhs.array->size-1
            if ( *lhs.array->items(i) = *rhs.array->items(i) ) = 0 then return 0
        next i
    case varType._OBJECT_
        if lhs.object->size <> rhs.object->size then return 0
        for i as integer = 0 to lhs.object->size-1
            if ( *lhs.object->fields(i) = *rhs.object->fields(i) ) = 0 then return 0
        next i
    end select
    
    return -1
end Operator

Destructor variable()
end Destructor

sub variable.init( byval s as string, byval n as string = "" )
    dim as integer l = len(s)
    dim as integer arrayIsOpen = 0
    dim as integer objectIsOpen = 0
    dim as integer inQuotes = 0
    
    this.lbl = n

    for i as integer = 0 to l-1
        dim as ubyte c = s[i]

        if isWhite( c ) then continue for
        
        if isNumberJson( c ) then
            if arrayIsOpen or objectIsOpen then
                this.typ = _MALFORMED_
                this.strng = s
                exit sub
            endif

            this.typ = _NUMBER_
            dim as string inNum = ""
            
            Do while IsNumberJson( s[i] )
                inNum += ascii( s[i] )
                if i > l then
                    this.typ = _MALFORMED_
                    this.strng = s 
                    ? "Error: i > l"
                    exit sub
                endif
                i+=1
            loop
            
            this.number = val(inNum)
        endif

        if c = 34 then
            if arrayIsOpen or objectIsOpen then
                this.typ = _MALFORMED_
                this.strng = s
                ? "Array / Object is open"
                exit sub
            endif
            
            i+=1
            this.typ = _STRING_
            dim as string inString = ""
            dim as integer done = 0
            Do 
                if s[i-1] <> asc("\") then
                    if s[i] <> 34 then
                        inString += ascii( s[i] )
                        i+=1
                    else
                        done = 1
                    endif
                else
                    inString += ascii( s[i] )
                    i+=1
                endif

                if i >= l then
                    this.typ = _MALFORMED_
                    this.strng = s
                    ? "Error: i > l"
                    done = 1
                endif
            loop until done = 1
            
            if inString <> "" then this.strng = unEscape( inString )            
         
            if i <> l-1 then
                this.typ = _MALFORMED_
                this.strng = s
                ? "Error: i <> l-1", i, l-1 
                ? instring
            endif
        endif
        
        select case c
            case asc("t"),asc("T"),asc("f"),asc("F"),asc("n"), asc("N")
                if mid(s,i+1,4) = "true" then
                    this.typ = _BOOL_
                    this.bool = _TRUE_
                    i += 3
                elseif mid(s,i+1,4) = "null" then
                    this.typ = _NULL_
                    i += 3
                elseif mid(s,i+1,5) = "false" then
                    this.typ = _BOOL_
                    this.bool = _FALSE_
                    i += 4
                endif
        
            case asc("[")
                arrayIsOpen = 1
                this.typ = _ARRAY_
                this.array = new varArray
                dim as integer level = 1
                dim as string instring = ""
                
                i+=1
                Do 
                    dim as ubyte char2 = s[i]
                    dim as variable tmp
                                        
                    select case char2
                        
                        case 34
                            if inQuotes = 0 then inQuotes = 1 else inQuotes = 0
                            instring += ascii( char2 )
                            
                        case asc("[")
                            level += 1 
                            instring += "["
                            Do
                                i+=1
                                if s[i] = asc("[") then level += 1
                                if s[i] = asc("]") then level -= 1
                                instring += ascii( s[i] )
                            loop until level = 1
                            if instring <> "" then
                                tmp.init( instring )
                                array->add( @tmp )
                                instring = ""
                            endif
                        case asc("]") 
                            if instring <> "" then
                                if isWhite( instring[0] ) = 0 then
                                    tmp.init( instring )
                                    array->add( @tmp )
                                endif
                            endif
                            instring = ""
                            level -= 1
                        case asc(",") 
                            if inQuotes = 0 then
                                if instring <> "" then
                                    tmp.init( instring )
                                    array->add( @tmp )
                                    instring = ""
                                endif
                            else
                                instring += ascii( char2 )
                            endif
                        case asc("{")
                            dim as integer olevel = 1
                            instring += "{"
                
                            Do 
                                i+=1
                                if s[i] = asc("{") then olevel += 1
                                if s[i] = asc("}") then olevel -= 1
                                instring += ascii( s[i] )
                            loop until olevel = 0
                            
                            if instring <> "" then
                                tmp.init( instring )
                                array->add( @tmp )
                                instring = ""
                            endif
                        case else
                            instring += ascii( char2 )
                            
                    end select
                    i+=1
                loop until level = 0
                arrayIsOpen = 0
            
            case asc("{")
                objectIsOpen = 1 
                this.typ = _OBJECT_
                this.object = new varObject
                dim as integer olevel = 1, alevel, inQuotes = 0
                dim as string instring = "", key = ""
                dim as variable tmp
                
                Do
                    i+=1
                    dim as ubyte char2 = s[i]                    
                    
                    if isWhite( char2 ) AND inQuotes = 0 then continue do

                    if inQuotes = 1 then
                        if char2 <> 34 then 
                            instring += ascii( char2 )
                            continue do
                        endif
                    endif
                    
                    select case char2                            
                        case asc(":")
                           key = instring
                           instring = ""
                        case asc("[")
                            alevel += 1
                            instring += ascii( char2 )
                        case asc("]")
                            alevel -= 1
                            instring += ascii( char2 )
                        case asc("{")
                            olevel += 1
                            instring += ascii( char2 )
                            
                            Do
                                i+=1
                                char2 = s[i]
                                if char2 = 34 then
                                    if inQuotes = 1 then inQuotes = 0 else inQuotes = 1 
                                endif

                                if isWhite( char2 ) and inQuotes = 0 then Continue do                                
                                if char2 = asc("{") then olevel += 1
                                if char2 = asc("}") then olevel -= 1
                                if char2 = asc("[") then alevel += 1
                                if char2 = asc("]") then alevel -= 1
                                instring += ascii( char2 )
                            loop until olevel = 1 and alevel = 0
                            
                            if instring <> "" then
                                tmp.init( instring )
                                object->add( key, @tmp )
                                instring = ""
                            endif                            
                        case asc("}")
                            olevel -= 1
                            if olevel = 0 then
                                if instring <> "" then
                                    tmp.init( instring )
                                    object->add( key, @tmp )
                                    instring = ""
                                endif
                            endif
                        case asc(",")
                            if alevel = 0 then
                                if instring <> "" then
                                    tmp.init( instring )
                                    object->add( key, @tmp )
                                    instring = ""
                                endif
                            else
                                instring += ascii( char2 )
                            endif
                        case 34
                            instring += ascii( char2 )
                            if inQuotes = 1 then inQuotes = 0 else inQuotes = 1

                        case else                        
                            instring += ascii( char2 )
                    end select
                loop until olevel = 0
                objectIsOpen = 0
                
        end select
    next i
    
end sub

function variable.getType() as string
    select case typ
    case _NUMBER_:
        return "Number"
    case _STRING_:
        return "String"
    case _BOOL_:
        return "Boolean"
    case _ARRAY_:
        return "Array"
    case _OBJECT_:
        return "Object"
    case _NULL_:
        return "null"
    case _MALFORMED_:
        return "[MALFORMED]"
    end select
end function

function variable.getTypeNum() as vartype
    return typ
end function

function variable.toString() as string
    select case typ
    case _NUMBER_:
        return number & ""
    case _STRING_:
        return strng
    case _BOOL_:
        if bool then return "true"
        return "false"
    case _ARRAY_:
        return "ARRAY"
    case _OBJECT_:
        return "OBJECT"
    case _NULL_:
        return "null"
    case _MALFORMED_:
        return "[MALFORMED]"
  end select
end function

function variable.getNumber() as double
    if typ <> _NUMBER_ then return 0
    return number
end function

function variable.getString() as string
    if typ <> _STRING_ then return ""
    return strng
end function

function variable.getBoolean() as integer
    if typ <> _BOOL_ then return _FALSE_
    return bool
end function

function variable.getArray() as vararray ptr
    if typ <> _ARRAY_ then return NULL
    return array
end function

function variable.getObject() as varobject ptr
    if typ <> _OBJECT_ then return NULL
    return object
end function

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Last edited by rolliebollocks on Jul 10, 2014 2:18, edited 6 times in total.
rolliebollocks
Posts: 2655
Joined: Aug 28, 2008 10:54
Location: new york

Re: json basic scripting language

Post by rolliebollocks »

jsb_varmap.bas

Code: Select all

#include once "vector.bi"
#include once "json_parser.bas"

initVector( variable )
initVector( string )
initVector( vectorVariable )

type jsb_var_map
    
    declare Constructor()
    declare Constructor( byref rhs as jsb_var_map )
    declare Operator Let( byref rhs as jsb_var_map )
    declare sub add( byref v as variable )
    declare sub pop( byref l as string )
    declare function find( byref l as string ) as variable ptr
    declare function findIdx( byref l as string ) as integer
    declare function size() as integer
    declare sub clear()
    
    dim as vectorVectorVariable vars
    dim as integer curScope = 0
end type

sub jsb_var_map.clear()
    for i as integer = 0 to vars.size-1
        vars[i].clear
    next i
    vars.clear
end sub

Constructor jsb_var_map()
    vars.resize( 1 )
end Constructor

Constructor jsb_var_map( byref rhs as jsb_var_map )
    this.vars = rhs.vars
end Constructor

Operator jsb_var_map.Let( byref rhs as jsb_var_map )
    if @vars <> @rhs.vars then
        this.vars = rhs.vars
    endif
end Operator

sub jsb_var_map.add( byref v as variable )
    vars[curScope].push_back( v )
end sub

sub jsb_var_map.pop( byref l as string )
    for i as integer = 0 to vars.size-1
        for ii as integer = 0 to vars[i].size-1
            if l = vars[i][ii].lbl then vars[i].pop( i )
        next ii
    next i
end sub

function jsb_var_map.find( byref l as string ) as variable ptr
    for i as integer = 0 to vars.size-1
        for ii as integer = 0 to vars[i].size-1
            if l = vars[i][ii].lbl then return @vars[i][ii]
        next ii
    next i
    return NULL
end function

function jsb_var_map.findIdx( byref l as string ) as integer
    for i as integer = 0 to vars.size-1
        for ii as integer = 0 to vars[i].size-1
            if l = vars[i][ii].lbl then return ii
        next ii
    next i
    return -1
end function

function jsb_var_map.size() as integer
    return vars.size
end function
Last edited by rolliebollocks on Jun 29, 2014 23:36, edited 5 times in total.
rolliebollocks
Posts: 2655
Joined: Aug 28, 2008 10:54
Location: new york

Re: json basic scripting language

Post by rolliebollocks »

jsb_function.bas

Code: Select all

#include once "vector.bi"
#include once "json_parser.bas"
#include once "jsb_varmap.bas"

#DEFINE JSB_FUNC_SIG function ( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable

type jsb_function
    
    Public:
        
        declare Constructor()
        declare Constructor( byref rhs as jsb_function )
        declare Operator Let( byref rhs as jsb_function )
        
        declare sub set( byref l as string, byref f as JSB_FUNC_SIG, byref s as string )
        declare function get() as JSB_FUNC_SIG
        declare function getLbl() as string
    
        
        as JSB_FUNC_SIG     func 
        as string           lbl  
        as string           signature 
        
end type

Constructor jsb_function()
end Constructor

Constructor jsb_function( byref rhs as jsb_function )
    this.func = rhs.func
    this.lbl = rhs.lbl
    this.signature = rhs.signature
end Constructor

Operator jsb_function.Let( byref rhs as jsb_function )
    if @this = @rhs then exit operator
    this.func = rhs.func
    this.lbl = rhs.lbl
    this.signature = rhs.signature
end Operator

sub jsb_function.set( byref l as string, byref f as JSB_FUNC_SIG, byref s as string )
    this.lbl = l
    this.func = f
    this.signature = s
end sub

function jsb_function.get() as JSB_FUNC_SIG
    return func
end function

function jsb_function.getLbl() as string
    return lbl
end function

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'                                                                              '
'                               Function Map                                   '
'                                                                              '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

initVector( jsb_function )

type jsb_function_map
    
    Public:
    
        declare Constructor
        declare Constructor( byref rhs as jsb_function_map )
        declare Operator Let( byref rhs as jsb_function_map )
        
        declare sub add( byref f as jsb_function )
        declare sub add( byval l as string, byref f as JSB_FUNC_SIG, byval s as string )
        
        declare function find( byval l as string ) as jsb_function ptr
    
    Protected:
    
        functions as vectorJsb_function

end type

Constructor jsb_function_map
end Constructor

Constructor jsb_function_map( byref rhs as jsb_function_map )
    this.functions = rhs.functions
end Constructor

Operator jsb_function_map.Let( byref rhs as jsb_function_map )
    if @this <> @rhs then
        this.functions = rhs.functions
    endif
end Operator

sub jsb_function_map.add( byref f as jsb_function )
    functions.push_back( f )
end sub

sub jsb_function_map.add( byval l as string, byref f as JSB_FUNC_SIG, byval s as string )
    dim as jsb_function func 
    func.set( l,f,s )
    functions.push_back( func )
end sub

function jsb_function_map.find( byval l as string ) as jsb_function ptr
    for i as integer = 0 to functions.size-1
        if functions[i].getLbl = l then return @functions[i]
    next i
    return 0
end function

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
type token_array_ as token_array

type jsb_user_func
    as string lbl
    as token_array_ ptr body
    as token_array_ ptr head
end type

initVector( jsb_user_func )

type jsb_user_func_ctx
    declare function find( byval s as string ) as jsb_user_func ptr
    declare sub add( byref j as jsb_user_func )
    
    as vectorJsb_user_func user_funcs
end type

function jsb_user_func_ctx.find( byval s as string ) as jsb_user_func ptr
    for i as integer = 0 to user_funcs.size - 1
        if user_funcs[i].lbl = s then return @user_funcs[i]
    next i
    return 0
end function

sub jsb_user_func_ctx.add( byref j as jsb_user_func )
    user_funcs.push_back( j )
end sub
    
    
Last edited by rolliebollocks on Jun 21, 2014 22:59, edited 3 times in total.
rolliebollocks
Posts: 2655
Joined: Aug 28, 2008 10:54
Location: new york

Re: json basic scripting language

Post by rolliebollocks »

jsb_error.bi

Code: Select all

enum errors
    SYNTAX_ERROR
    ILLEGAL_FUNCTION_CALL
    MISSING_QUOTE_IN_LITERAL_STRING
    OPEN_ARRAY_NOT_CLOSED
    UNDEFINED_REFERENCE
    OPEN_OBJECT_NOT_CLOSED
    NO_SUCH_FUNCTION
    VARIABLE_NOT_DECLARED
    TYPE_MISMATCH
    MALFORMED_VAR
    ARRAY_OUT_OF_BOUNDS
    INVALID_OBJECT_KEY
end enum

function jsb_throw_error( byval num as errors ) as string 
    select case num
        case NO_SUCH_FUNCTION
            return "Function not defined"
        case SYNTAX_ERROR
            return "Syntax Error"
        case ILLEGAL_FUNCTION_CALL
            return "Illegal Function Call"
        case MISSING_QUOTE_IN_LITERAL_STRING
            return "Missing quote in literal string"
        case OPEN_ARRAY_NOT_CLOSED
            return "Expected: ']'"
        case UNDEFINED_REFERENCE
            return "Undefined Reference"
        case OPEN_OBJECT_NOT_CLOSED
            return "Expected: }"
        case VARIABLE_NOT_DECLARED
            return "Variable not declared"
        case TYPE_MISMATCH
            return "Type Mismatch"
        case MALFORMED_VAR
            return "Malformed Variable"
        case ARRAY_OUT_OF_BOUNDS
            return "Array out of bounds"
        case INVALID_OBJECT_KEY
            return "Object key not found"
        case else
            return "Error: Halting Execution at line "
    end select
end function

#macro lex_assert( expression, iferr, linenum )
    Scope
        if expression = 0 then
            dim as string errstr = "Line: " & linenum & " " & jsb_throw_error( iferr ) 
            Color 12
            print errstr
            done = 1
            exit do            
        end if
    end Scope
#endmacro

#macro parse_assert( expression, iferr, linenum, msg )
    scope
        if expression = 0 then
            dim as string errstr = jsb_throw_error( iferr ) 
            Color 12
            print errstr + " ";
            Color 15
            print msg
            Color 7
            return "null"
        endif
    end scope
#endmacro

#macro func_assert( expression, iferr, msg )
    scope
        if expression = 0 then
            dim as string errstr = jsb_throw_error( iferr )
            Color 12
            print errstr + " ";
            Color 15
            print msg
            Color 7
            return "null"
        endif
    end scope
#endmacro
Last edited by rolliebollocks on Jul 10, 2014 2:19, edited 3 times in total.
rolliebollocks
Posts: 2655
Joined: Aug 28, 2008 10:54
Location: new york

Re: json basic scripting language

Post by rolliebollocks »

jsb_lexer.bas

Code: Select all

#include once "vector.bi"
#include once "jsb_error.bi"
#include once "json_parser.bas"
#include once "jsb_function.bas"

#DEFINE DBLQUOTE ascii(34)

dim shared as string user_funcs
dim shared as jsb_user_func_ctx user_func_ctx

function is_user_func( byval s as string ) as integer
    dim as string this_func = ","+s+","
    return instr( user_funcs, this_func )
end function

function is_jsb_func( byval s as string ) as integer
    dim as string all_func_names = ",var,function,print,sqr,+,/,*,^,%," _
                                 + "sin,cos,tan,asin,acos,atan,atan2,sqr,abs," _
                                 + "log,fix,int,frac,sgn,rnd,mod," _
                                 + "len,asc,chr,left,right,mid,lcase,ucase,instr," _
                                 + "pluck,load_file_as_string,beep," _
                                 + "length,pop,push,sleep,push_back,last,first," _
                                 + "size,split,slice,typeof,clear,cls," _
                                 + ""
    dim as string this_func = ","+s+","
    return instr( all_func_names, this_func )
end function


function is_bit_op( byval s as string ) as integer
    dim as string all_bit_ops   = ",and,&&,or,||," _
                                + ""
    dim as string this_op = ","+s+","
    return instr( all_bit_ops, this_op )
end function

enum token_typ
    _ANY_
    _BOOL_
    _FUNCTION_
    _USER_FUNC_
    _DBL_QUOTE_
    _STRING_
    _END_LINE_
    _OPEN_PAREN_
    _CLOSE_PAREN_
    _OPEN_BRACE_
    _CLOSE_BRACE_
    _OPEN_CBRACE_
    _CLOSE_CBRACE_
    _NUMBER_
    _MATHOP_
    _ARRAY_
    _OBJECT_
    _EQUAL_ASSIGN_
    _EQUAL_COMPARE_
    _GREATER_THAN_
    _LESS_THAN_
    _EQUAL_OR_GREATER_
    _EQUAL_OR_LESS_
    _NOT_EQUAL_
    _NOT_
    _VAR_NAME_
    _BACKSLASH_
    _FWDSLASH_
    _DOT_
    _COMMA_
    _UNTOKENED_EXPRESSION_
    _IF_
    _ELSE_
    _WHILE_
    _BITOP_
    _TRUE_
    _FALSE_
    _FOR_
    _TO_
    _STEP_
    _RETURN_
    _SELECT_
    _CASE_
    _COMMENT_
    _EVAL_
    _PARSE_
    _OUT_
end enum

type token
    declare Constructor()
    declare Operator Let( byref rhs as token )
    declare Operator Let( byref rhs as variable )
    declare Constructor ( byref rhs as token )
    declare Constructor ( byref rhs as variable )
    declare Constructor( byval typ as token_typ, byval t as string )
    declare function toString() as string
    
    as token_typ    myType
    as variable     value
end type 

Constructor token()
end Constructor

Constructor token( byref rhs as token )
    this.myType = rhs.myType
    this.value  = rhs.value
end Constructor

Operator token.Let( byref rhs as token )
    this.myType = rhs.myType
    this.value  = rhs.value
end Operator

Constructor token( byref rhs as variable )
    select case rhs.typ
    case varType._ARRAY_ 
        this.myType = token_typ._ARRAY_
        this.value  = rhs
    case varType._OBJECT_
        this.myType = token_typ._OBJECT_
        this.value  = rhs
    case varType._NUMBER_
        this.myType = token_typ._NUMBER_
        this.value  = rhs
    case varType._STRING_
        this.myType = token_typ._STRING_
        this.value  = rhs
    case varType._BOOL_
        if rhs.bool = JSON_BOOL._TRUE_ then
            this.myType = token_typ._TRUE_
            this.value = "true"
        else
            this.myType = token_typ._FALSE_
            this.value = "false"
        endif
    end select
end Constructor

Operator token.Let( byref rhs as variable )
    select case rhs.typ
    case varType._ARRAY_ 
        this.myType = token_typ._ARRAY_
        this.value  = rhs
    case varType._OBJECT_
        this.myType = token_typ._OBJECT_
        this.value  = rhs
    case varType._NUMBER_
        this.myType = token_typ._NUMBER_
        this.value  = rhs
    case varType._STRING_
        this.myType = token_typ._STRING_
        this.value  = rhs
    case varType._BOOL_
        if rhs.bool = JSON_BOOL._TRUE_ then
            this.myType = token_typ._TRUE_
            this.value = "true"
        else
            this.myType = token_typ._FALSE_
            this.value = "false"
        endif
    end select
end Operator

Constructor token( byval typ as token_typ, byval v as string )
    this.myType = typ
    this.value  = v
end Constructor

function token.toString () as string
    dim as string res = ""
    
    select case this.myType
    case token_typ._COMMENT_              : res = "COMMENT"
    case token_typ._CASE_                 : res = "CASE"
    case token_typ._SELECT_               : res = "SELECT"
    case token_typ._FOR_                  : res = "FOR"
    case token_typ._TO_                   : res = "TO"
    case token_typ._STEP_                 : res = "STEP"
    case token_typ._TRUE_                 : res = "TRUE"
    case token_typ._FALSE_                : res = "FALSE"
    case token_typ._BITOP_                : res = "BITWISE OPERATOR " + this.value.toString
    case token_typ._WHILE_                : res = "while"
    case token_typ._ELSE_                 : res = "else"
    case token_typ._IF_                   : res = "if"
    case token_typ._ANY_                  : res = "ANY: " + this.value.toString
    case token_typ._FUNCTION_             : res = "FUNCTION: " + this.value.toString
    case token_typ._DBL_QUOTE_            : res = "Double Quote"
    case token_typ._STRING_               : res = "STRING: " + this.value.toString
    case token_typ._END_LINE_             : res = "End Line"
    case token_typ._OPEN_BRACE_           : res = "["
    case token_typ._CLOSE_BRACE_          : res = "]"
    case token_typ._NUMBER_               : res = "NUMBER: " + this.value.toString
    case token_typ._MATHOP_               : res = "MATH OP: " + this.value.toString
    case token_typ._ARRAY_                : res = "ARRAY: " + this.value.toString
    case token_typ._OBJECT_               : res = "OBJECT: " + this.value.toString
    case token_typ._EQUAL_ASSIGN_         : res = "= (Equal Assign)"
    case token_typ._EQUAL_COMPARE_        : res = "== (Equal Compare)"
    case token_typ._GREATER_THAN_         : res = ">"
    case token_typ._LESS_THAN_            : res = "<"
    case token_typ._EQUAL_OR_GREATER_     : res = ">="
    case token_typ._EQUAL_OR_LESS_        : res = "<="
    case token_typ._NOT_EQUAL_            : res = "!="
    case token_typ._NOT_                  : res = "! (Not)"
    case token_typ._VAR_NAME_             : res = "VAR NAME: " + this.value.toString
    case token_typ._OPEN_PAREN_           : res = "("
    case token_typ._CLOSE_PAREN_          : res = ")"
    case token_typ._OPEN_CBRACE_          : res = "{"
    case token_typ._CLOSE_CBRACE_         : res = "}"
    case token_typ._BACKSLASH_            : res = "\"
    case token_typ._FWDSLASH_             : res = "/"
    case token_typ._DOT_                  : res = "."
    case token_typ._COMMA_                : res = ","
    case token_typ._USER_FUNC_            : res = "User Function: " + this.value.toString
    case token_typ._UNTOKENED_EXPRESSION_ : res = "UNTOKENED EXPRESSION: " + this.value.toString
    case token_typ._RETURN_               : res = "RETURN"
    case token_typ._EVAL_                 : res = "EVAL"
    case token_typ._PARSE_                : res = "PARSE"
    case token_typ._OUT_                  : res = "OUT"
    end select
    
    return res
end function

initVector( token )

type token_array
    declare Constructor()
    declare Constructor( byref rhs as token_array )
    declare Operator Let( byref rhs as token_array )
    
    declare sub init( byval s as string )
    declare function toString() as string
    declare function find( byval tk as token_typ, byval bgn as integer = 0 ) as integer
    declare function findPtr( byval tk as token_typ, byval bgn as integer = 0 ) as token ptr
    declare function find( byref tk as token_array, byval bgn as integer = 0 ) as integer
    
    declare sub clear()
    
    as vectorToken tokens
end type

Operator + ( byref lhs as token_array, byref rhs as token_array ) as token_array
    var res = lhs
    for i as integer = 0 to rhs.tokens.size-1
        res.tokens.push_back( rhs.tokens[i] )
    next i
    
    return res
end Operator

declare function jsb_user_func_set( byref f as token_array ) as jsb_user_func

Constructor token_array()
end Constructor

Constructor token_array( byref rhs as token_array )
    this.tokens = rhs.tokens
end Constructor

Operator token_array.Let( byref rhs as token_array )
    this.tokens = rhs.tokens
end Operator

sub token_array.init( byval s as string )
    
    #macro addToken(typ_,text,arr)
    Scope
        dim as token t
        t.myType = typ_
    
        select case typ_
        case token_typ._NUMBER_
            t.value = val( text )
        case token_typ._STRING_, token_typ._VAR_NAME_, _
             token_typ._FUNCTION_, _MATHOP_, _USER_FUNC_, _
                       _UNTOKENED_EXPRESSION_, _EQUAL_ASSIGN_, _BITOP_
            
            t.value.typ = varType._STRING_
            if typ_ = token_typ._STRING_ then
                if text <> "" then
                    t.value.strng = unescape( text )
                endif
            else
                t.value.strng = text
            endif
        case _DBL_QUOTE_,  _EQUAL_COMPARE_
        case else
            if text <> "" then
                t.value = text
            endif
        end select
        
        arr.push_back( t )
    End Scope
    #endmacro
    
    #macro check_quotes()
        if inQuotes = 1 then
            check1 += ascii( s[i] )
            Continue do
        endif
    #endmacro
    
    #macro var_or_func(arr)
    Scope
        dim as token t
        if is_jsb_func( check1 ) then
            addToken(_FUNCTION_,check1,arr)
            check1 = ""
        elseif is_user_func( check1 ) then
            addToken(_USER_FUNC_,check1,arr)
            check1 = ""
        elseif is_bit_op( check1 ) then
            addToken(_BITOP_,check1,arr)
            check1 = ""
        elseif check1 = "if" then
            addToken(_IF_,"",arr)
            check1 = ""
        elseif check1 = "-" then
            addToken(_MATHOP_,"-",arr)
            check1 = ""
        elseif check1 = "else" then
            addToken(_ELSE_,"",arr)
            check1 = ""
        elseif check1 = "while" then
            addToken(_WHILE_,"",arr)
            check1 = ""
        elseif check1 = "for" then
            addToken(_FOR_,"",arr)
            check1 = ""
        elseif check1 = "to" then
            addToken(_TO_,"",arr) 
            check1 = ""
        elseif check1 = "step" then
            addToken(_STEP_,"",arr)
            check1 = ""
        elseif check1 = "return" then
            addToken(_RETURN_,"",arr)
            check1 = ""
        elseif check1 = "switch" then
            addToken(_SELECT_,"",arr)
            check1 = ""
        elseif check1 = "select" then
            addToken(_SELECT_,"",arr)
            check1 = ""
        elseif check1 = "case" then
            addToken(_CASE_,"",arr)
            check1 = ""
        elseif check1 = "eval" then
            addToken(_EVAL_,"",arr)
            check1 = ""
        elseif check1 = "parse" then
            addToken(_PARSE_,"",arr)
            check1 = ""
        elseif check1 = "out" then
            addToken(_OUT_,"",arr)
            check1 = ""
        elseif val(check1) orelse check1 = "0" then
            addToken(token_typ._NUMBER_,check1,arr)
            check1 = ""
        elseif check1 <> "" then
            addToken(_VAR_NAME_,check1,arr)
            check1 = ""
        endif
    end Scope
    #endmacro
    
    s += " "
    dim as integer done = 0
    dim as string check1 = ""
    dim as integer i = -1
    dim as integer inQuotes = 0
    dim as integer linenum = 1
    dim as integer length = len( s )
    
    Do while done = 0 
                
        i += 1
        if i >= length then done = 1
        
        select case s[i]
        
            case asc("'")
                check_quotes()
                
                if check1 <> "" then
                    var_or_func(tokens)
                endif
                
                addToken(_COMMENT_,"",tokens)
            
            case asc(">")
                check_quotes()
                
                if check1 <> "" then
                    var_or_func(tokens)
                endif
                if i < length - 2 andalso s[i+1] = asc("=") then
                    i+=1
                    addToken(_EQUAL_OR_GREATER_,"",tokens)
                else
                    addToken(_GREATER_THAN_,"",tokens)
                endif
            
            case asc("<")
                check_quotes()
                
                if check1 <> "" then
                    var_or_func(tokens)
                endif
                if i < length - 2 andalso s[i+1] = asc("=") then
                    i+=1
                    addToken(_EQUAL_OR_LESS_,"",tokens)
                elseif i < length - 2 andalso s[i+1] = asc(">") then
                    i+=1
                    addToken(_NOT_EQUAL_,"",tokens)
                else
                    addToken(_LESS_THAN_,"",tokens)
                endif
                
            case asc ("!")
                check_quotes()
                
                if check1 <> "" then
                    var_or_func(tokens)
                endif
                
                if i < length - 2 andalso s[i+1] = asc("=") then
                    i+=1
                    addToken(_NOT_EQUAL_,"",tokens)
                else
                    addToken(_NOT_,"",tokens)
                endif
                
            case asc(",")
                check_quotes()
                
                if check1 <> "" then
                    var_or_func(tokens)
                endif
                addToken(_COMMA_,"",tokens)
                
            case asc(".")
                check_quotes()
                
                if i < length-1 then
                    if isNumberJson( s[i+1] ) then
                        check1 += ascii( s[i] )
                        Continue do
                    else
                        if check1 <> "" then
                            var_or_func(tokens)
                        endif
                        addToken(_DOT_,"",tokens)
                    endif
                endif
                       
            case asc("\")
                lex_assert(inQuotes=1, UNDEFINED_REFERENCE, linenum)
                check1 += ascii( s[i] )
                check1 += ascii( s[i+1] )
                i += 1
                          
            case asc("(")
                check_quotes()
                
                if check1 <> "" then
                    var_or_func(tokens)
                endif
                
                addToken(_OPEN_PAREN_,"",tokens)
            
            case asc(")")
                check_quotes()
                
                if check1 <> "" then
                    var_or_func(tokens)
                endif
                
                addToken(_CLOSE_PAREN_,"",tokens)
            
            case asc("}")
                
                check_quotes()
                
                if check1 <> "" then
                    var_or_func(tokens)
                endif
                
                addToken(_CLOSE_CBRACE_,"",tokens)
            
            case asc("{") 
                
                check_quotes()
                
                if tokens.size >= 3 andalso tokens[ tokens.size - 3 ].value.strng = "var" then
                    
                    check1 += "{"
                    dim as integer olevel = 1
                    
                    Do
                        
                        i+=1
                        lex_assert( i <= length, OPEN_OBJECT_NOT_CLOSED, linenum )
                        if s[i] = asc("{") then
                            olevel += 1
                            check1 += ascii( s[i] )
                        elseif s[i] = asc("}") then
                            olevel -= 1
                            check1 += ascii( s[i] )
                        else
                            check1 += ascii( s[i] )
                        endif
                    
                    Loop until olevel = 0
                    
                    addToken(token_typ._OBJECT_,check1,tokens)
                    check1 = "" 
                    'i+=1
                    
                else
                    
                    addToken( _OPEN_CBRACE_,"",tokens )
                    
                endif 'if tokens[ tokens.size - 3 ].txt = "var" then
                
            case asc("[")
            
                check_quotes()
                                
                if check1 = "" then
                    
                    if tokens.size > 1 andalso tokens[tokens.size-1].myType <> _CLOSE_BRACE_ then
                    
                        addToken(_OPEN_BRACE_,"",tokens)
                        
                        dim as integer alevel = 1
                        check1+="["
                        
                        Do
                            i+=1
                            lex_assert( i <= length, OPEN_ARRAY_NOT_CLOSED, linenum )
                            if s[i] = asc("[") then
                                alevel += 1
                                check1 += ascii( s[i] )
                            elseif s[i] = asc("]") then
                                alevel -= 1
                                check1 += ascii( s[i] )
                            else
                                check1 += ascii( s[i] )
                            endif
                        loop until alevel = 0
                        
                        addToken(token_typ._ARRAY_,check1,tokens)
                        addToken(_CLOSE_BRACE_,"",tokens)
                        check1 = ""
                    
                    else
                        
                        addToken( _OPEN_BRACE_,"",tokens )
                        
                    endif
                    
                else
                                        
                    addToken(_VAR_NAME_,check1,tokens)
                    check1 = ""
                    dim as integer alevel = 1
                    addToken(_OPEN_BRACE_,"",tokens)
                    
                endif 'if check1 <> ""
                
            case asc("]")
                
                check_quotes()
                
                if check1 <> "" then
                    var_or_func(tokens)
                endif
                
                addToken(_CLOSE_BRACE_,"",tokens)
                
            case asc("=")

                if check1 <> "" then 
                    var_or_func(tokens)
                endif
                
                if inQuotes = 1 then
                    check1 += ascii( s[i] )
                    Continue do
                elseif s[i+1] = asc("=") then
                    i+=1
                    addToken(_EQUAL_COMPARE_,"",tokens)
                else
                    addToken(_EQUAL_ASSIGN_,"=",tokens)
                endif
                
            case asc(";")
                check_quotes()
                if check1 <> "" then
                    var_or_func(tokens)
                endif
                addToken(_END_LINE_,"",tokens)
                linenum += 1
            
            case asc("0") to asc("9"), asc("-"), asc(".")
                check_quotes()

                if val(check1) = 0 andalso s[i] = asc(".") then
                    var_or_func(tokens)
                    addToken(_DOT_,"",tokens)                
                elseif val(check1) andalso s[i] = asc("-") then
                    addToken(token_typ._NUMBER_, check1,tokens)
                    addToken(_MATHOP_, "-",tokens)
                    check1 = ""
                    Continue do                                    
                else
                    if tokens.size then
                        if tokens[ tokens.size-1 ].myType = token_typ._NUMBER_ andalso s[i] = asc("-") then
                            if check1 <> "" then
                                addToken(token_typ._NUMBER_,check1,tokens)
                            endif
                            addToken(_MATHOP_, ascii(s[i]),tokens)
                            Continue do
                        elseif tokens[ tokens.size-1 ].myType = token_typ._VAR_NAME_ andalso s[i] = asc("-") then                            
                            addToken(_MATHOP_, ascii(s[i]),tokens)
                            Continue do
                        endif
                        
                    endif
                    
                    if check1 <> "" andalso s[i] = asc("-") then
                        var_or_func(tokens)
                        addToken( _MATHOP_, "-",tokens )
                        Continue do
                    endif
                    
                    check1 += ascii( s[i] ) 
                endif 
                
            case asc("+"), asc("/"), asc("*"), asc("%"), asc("^")
                
                check_quotes()
                
                if check1 <> "" then
                    var_or_func(tokens)
                endif
                
                addToken(_MATHOP_,ascii(s[i]),tokens)
                                
            case 9, 10, 13, 32
                check_quotes()
                
                if check1 = "function" then
                    
                    dim as token_array func
                    addToken(_FUNCTION_,check1,func.tokens)
                    check1 = ""
                    i+=1
                    
                    Do
                        check1 += ascii( s[i] )
                        if i > length-1 then
                            lex_assert( 0, SYNTAX_ERROR, linenum )
                        endif
                        i+=1
                    loop until s[i] = asc("(")
                    
                    addToken(_USER_FUNC_,check1,func.tokens)
                    user_funcs += ","+check1+","
                    check1 = ""
                    
                    Do
                        check1 += ascii( s[i] )
                        if i > length-1 then
                            lex_assert( 0, SYNTAX_ERROR, linenum )
                        endif
                        i += 1
                    loop until s[i] = asc(")")
                    
                    func.init( check1+")" )
                    check1 = ""
                    
                    i = inStr(i,s,"{")
                    dim as integer cb_level = 1
                    
                    Do
                        i+=1
                        if i > length-1 then
                            lex_assert( 0, SYNTAX_ERROR, linenum )
                        endif
                        if s[i] = asc("{") then cb_level += 1
                        if s[i] = asc("}") then cb_level -= 1
                        
                        if s[i] = 10 orelse s[i] = 13 orelse s[i] = 9 then 
                            check1 += " "
                        else
                            check1 += ascii( s[i] )
                        endif
                    loop until cb_level = 0

                    func.init( check1 )
                    check1 = ""
                    
                    addToken( _END_LINE_,"", func.tokens )
                    i+=1
                    
                    dim as jsb_user_func j = jsb_user_func_set( func )                
                    user_func_ctx.add( j )
                    
                else
                    if check1 <> "" then
                        var_or_func(tokens)
                    endif
                    
                endif 'if check1 = "function"
                                                
            case asc("a") to asc("z"), asc("A") to asc("Z"), asc("_")
                check1 += ascii( s[i] )
                
            case 34
                if inQuotes = 0 then inQuotes = 1 else inQuotes = 0
                                
                if inQuotes = 0 then
                    addToken(token_typ._STRING_,check1,tokens)
                    check1 = ""
                endif
                
                'addToken(_DBL_QUOTE_,"",tokens)
            
            case else
                check_quotes()
                check1 += ascii( s[i] )
        end select
        
    loop
    
end sub

function token_array.toString() as string
    dim as string res = ""
    
    for i as integer = 0 to tokens.size-1
        select case this.tokens[i].myType
        case token_typ._COMMENT_            : res += "'"
        case token_typ._SELECT_             : res += "select"
        case token_typ._CASE_               : res += " case "
        case token_typ._STEP_               : res += " step "
        case token_typ._TO_                 : res += " to "
        case token_typ._FOR_                : res += "for "
        case token_typ._TRUE_               : res += " true "
        case token_typ._FALSE_              : res += " false "
        case token_typ._BITOP_              : res += this.tokens[i].value.toString
        case token_typ._WHILE_              : res += " while "
        case token_typ._ELSE_                : res += " else "
        case token_typ._IF_                  : res += " if "
        case token_typ._ANY_                  : res += "ANY: " + this.tokens[i].value.toString
        case token_typ._COMMA_            : res += ","
        case token_typ._FUNCTION_         : res += " "+this.tokens[i].value.toString + " "
        case token_typ._DBL_QUOTE_        : res += chr(34)
        case token_typ._STRING_           : res += this.tokens[i].value.toString
        case token_typ._END_LINE_         : res += ";" '+ !"\r\n"
        case token_typ._OPEN_BRACE_       : res += "["
        case token_typ._CLOSE_BRACE_      : res += "]"
        case token_typ._NUMBER_           : res += " "+this.tokens[i].value.toString+" "
        case token_typ._MATHOP_           : res += this.tokens[i].value.toString
        case token_typ._ARRAY_            : res += this.tokens[i].value.toString
        case token_typ._OBJECT_           : res += this.tokens[i].value.toString
        case token_typ._EQUAL_ASSIGN_     : res += " = " 
        case token_typ._EQUAL_COMPARE_    : res += " == "
        case token_typ._EQUAL_COMPARE_        : res += "== (Equal Compare)"
        case token_typ._GREATER_THAN_         : res += ">"
        case token_typ._LESS_THAN_            : res += "<"
        case token_typ._EQUAL_OR_GREATER_     : res += ">="
        case token_typ._EQUAL_OR_LESS_        : res += "<="
        case token_typ._NOT_EQUAL_            : res += "!="
        case token_typ._NOT_              : res += "!"
        case token_typ._VAR_NAME_         : res += " "+this.tokens[i].value.toString + " "
        case token_typ._CLOSE_PAREN_      : res += " ) "
        case token_typ._OPEN_PAREN_       : res += " ( "
        case token_typ._OPEN_CBRACE_          : res += " { "
        case token_typ._CLOSE_CBRACE_         : res += " } "
        case token_typ._BACKSLASH_        : res += "\"
        case token_typ._FWDSLASH_         : res += "/"
        case token_typ._DOT_              : res += "."
        case token_typ._USER_FUNC_    : res += this.tokens[i].value.toString
        case token_typ._UNTOKENED_EXPRESSION_ : res += this.tokens[i].value.toString 
        case token_typ._EVAL_                   : res += " eval "
        case token_typ._PARSE_                  : res += " parse "
        case token_typ._RETURN_                 : res += " return "
        case token_typ._OUT_                    : res += " out "
        end select
    next
    
    return res
end function

function token_array.find( byval tk as token_typ, byval bgn as integer = 0 ) as integer
    for i as integer = bgn to tokens.size-1
        if tk = tokens[i].myType then return i
    next i
    return -1
end function

function token_array.find( byref tk as token_array, byval bgn as integer = 0 ) as integer
    dim as integer position = -1
    for i as integer = bgn to tokens.size-1
        if tk.tokens[0].myType = tokens[i].myType then 
            position = i 
            for ii as integer = 0 to tk.tokens.size-1
                if ( tk.tokens[ii].myType <> this.tokens[ii+i].myType ) orelse _ 
                     tk.tokens[ii].value.tostring <> this.tokens[ii+i].value.tostring then
                        position = -1
                        exit for
                endif
            next
            if position <> -1 then return position
        endif
    next i
    return -1
end function

function token_array.findPtr( byval tk as token_typ, byval bgn as integer = 0 ) as token ptr
    for i as integer = bgn to tokens.size-1
        if tk = tokens[i].myType then return @tokens[i]
    next i
    return 0
end function

sub token_array.clear()
    tokens.clear
end sub
      
function sig_to_tokens( byref s as string ) as token_array
    dim as token_array res
    s += " "
    dim as integer l = len(s)
    dim as string check1 = ""
    
    #macro addToken(typ)
        dim as token t
        t.myType = typ
        res.tokens.push_back( t )
        check1 = ""
    #endmacro
    
    for i as integer = 0 to l-1
        select case check1
            case "("
                addToken(_OPEN_PAREN_)
            case ")"
                addToken(_CLOSE_PAREN_)
            case "%f" 
                addToken(_FUNCTION_)
            case "%v"
                addToken(_VAR_NAME_)
            case "%a"
                addToken(_ANY_)
            case "="
                addToken(_EQUAL_ASSIGN_)
            case else
                check1 += ascii( s[i] )
        end select
    next i
    
    return res
end function

function count_params( byref tk as token_array ) as integer
    dim as integer nparams = 0
    for i as integer = 0 to tk.tokens.size-1
        select case tk.tokens[i].myType
        case token_typ._VAR_NAME_         : nparams += 1
        case token_typ._ANY_              : nparams += 1
        case token_typ._FUNCTION_         : nparams += 1
        case token_typ._NUMBER_           : nparams += 1
        case token_typ._STRING_           : nparams += 1
        case token_typ._ARRAY_            : nparams += 1
        case token_typ._OBJECT_           : nparams += 1
        case token_typ._USER_FUNC_        : nparams += 1
        end select
    next i
    return nparams
end function

function get_rhs( byref tk as token_array, byval typ as token_typ ) as token_array
    dim as token_array res
    dim as integer idx = tk.find( typ ) + 1
    for i as integer = idx to tk.tokens.size-1
        res.tokens.push_back( tk.tokens[i] )
    next i
    return res
end function

function get_lhs( byref tk as token_array, byval typ as token_typ ) as token_array
    dim as token_array res
    dim as integer idx = tk.find( typ ) - 1
    for i as integer = 0 to idx
        res.tokens.push_back( tk.tokens[i] )
    next i
    return res
end function

function cut_right( byref tk as token_array, byval idx as integer ) as token_array
    dim as token_array res 
    for i as integer = idx to tk.tokens.size-1
        res.tokens.push_back( tk.tokens[i] )
    next i
    return res
end function

function cut_left( byref tk as token_array, byval idx as integer ) as token_array
    dim as token_array res
    for i as integer = 0 to idx
        res.tokens.push_back( tk.tokens[i] )
    next i
    return res
end function

function cut_idx( byref tk as token_array, byval start as integer, finish as integer ) as token_array
    dim as token_array res
    if start < 0 then return res
    if finish > tk.tokens.size-1 then return res
    
    for i as integer = start to finish
        res.tokens.push_back( tk.tokens[i] )
    next i
    
    return res
end function

function cut_out( byref tk as token_array, byval start as integer, finish as integer ) as token_array
    dim as token_array res = tk
    if start < 0 then return res
    if finish > tk.tokens.size-1 then return res
    
    for i as integer = start to finish
        res.tokens.pop( start )
    next i
    
    return res
end function

function rem_tkn( byref tk as token_array, typ as token_typ ) as token_array
    dim as token_array res
    
    for i as integer = 0 to tk.tokens.size-1
        if tk.tokens[i].myType <> typ then
            res.tokens.push_back( tk.tokens[i] )
        endif
    next i
    
    return res
end function

function jsb_user_func_set( byref f as token_array ) as jsb_user_func
    dim as integer i = 0
    dim as jsb_user_func res
    dim as token_array h
    dim as token_array b
    
    res.lbl = f.findPtr( _USER_FUNC_ )->value.strng
    
    dim as integer cb_level = 0

    Do
        h.tokens.push_back( f.tokens[i] )
        if f.tokens[i].myType = _CLOSE_PAREN_ then exit do
        if i > f.tokens.size-1 then exit do
        i+=1
    loop
    
    cb_level += 1
    
    Do
        i+=1
        if f.tokens[i].myType = _CLOSE_CBRACE_ then cb_level -= 1
        if f.tokens[i].myType = _OPEN_CBRACE_ then cb_level += 1
        if i > f.tokens.size-1 then exit do
        if cb_level = 0 then exit do
        b.tokens.push_back( f.tokens[i] )
    loop
    
    res.head = new token_array
    res.body = new token_array

    *res.head = h
    *res.body = b
    
    return res
end function

Last edited by rolliebollocks on Jul 12, 2014 22:12, edited 14 times in total.
rolliebollocks
Posts: 2655
Joined: Aug 28, 2008 10:54
Location: new york

Re: json basic scripting language

Post by rolliebollocks »

jsb_functions.bas

Code: Select all

#include once "jsb_function.bas"
#include once "jsb_lexer.bas"
#include once "jsb_error.bi"
#include once "crt.bi"

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'                                                                               '
'                   Variable Instantiation & Assignment                         '
'                                                                               '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

function _VAR( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    func_assert( args.size = 2, ILLEGAL_FUNCTION_CALL, "var" )
    func_assert( args[0].typ = varType._STRING_, ILLEGAL_FUNCTION_CALL, args[0].getType )
    
    dim as string lbl = args[0].strng
    
    if args[1].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[1].strng )
        if check then
            dim as variable n = *check
            n.lbl = lbl
            varMap->add( n )
        else
            args[1].lbl = lbl
            varMap->add( args[1] )
        endif
    else
        args[1].lbl = lbl
        varMap->add( args[1] )
    endif
    
    return "true"
end function

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

function _ASSIGN( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    
    'func_assert( args[0].typ = varType._STRING_, ILLEGAL_FUNCTION_CALL, args[0].getType )
    
    dim as string lbl = args[0].strng
    
    dim as variable ptr lhs = varMap->find( lbl )
    
    func_assert( lhs, VARIABLE_NOT_DECLARED, lbl )

    dim as variable ptr rhs 
    
    if args.size = 2 then    
        if args[1].typ = varType._STRING_ then
            rhs = varMap->find( args[1].strng )
            if rhs then 
                *lhs = *rhs
                lhs->lbl = lbl
            else
                *lhs = args[1]
                lhs->lbl = lbl
            endif
        else
            *lhs = args[1]
            lhs->lbl = lbl
        endif
    elseif args.size = 3 then
        dim as variable ptr idx 
        dim as integer idx_val = 0
        dim as string idx_str = ""
        
        if args[1].typ = varType._STRING_ then
            idx = varMap->find( args[1].strng )
            if idx then
                if idx->typ = varType._NUMBER_ then
                    idx_val = idx->number
                elseif idx->typ = varType._STRING_ then
                    idx_str = idx->strng
                endif
            else
                idx_str = args[1].strng
            endif
        else
            'func_assert( args[1].typ = _NUMBER_, TYPE_MISMATCH, args[1].tostring )
            if args[1].typ = varType._NUMBER_ then
                idx_val = args[1].number
            elseif args[1].typ = varType._STRING_ then
                idx_str = args[1].strng
            endif
        endif
        
        dim as variable ptr value
        dim as variable assign_val
        if args[2].typ = varType._STRING_ then
            value = varMap->find( args[2].strng )
            if value then 
                assign_val = *value
            else 
                assign_val = args[2]            
            endif
        else
            assign_val = args[2]            
        endif
        
        if lhs->typ = varType._ARRAY_ then
            func_assert( idx_val < lhs->array->size, ARRAY_OUT_OF_BOUNDS, idx_val )
            *lhs->array->items( idx_val ) = assign_val
        elseif lhs->typ = varType._OBJECT_ then
            dim as variable ptr check2 = lhs->object->get( idx_str )
            func_assert( check2, INVALID_OBJECT_KEY, idx_str )
            *check2 = assign_val
        endif
        
    endif
    
    return "true"
    
end function

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'                                                                               '
'                             Console Output                                    '
'                                                                               '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

function _PRINT( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
       
    func_assert( args.size = 1, ILLEGAL_FUNCTION_CALL, "PRINT" )
    
    dim as string value = args[0].tostring
    dim as variable ptr check = varMap->find( value )
    
    if check then
        print check->toString
    else    
        print value
    endif
    
    return "true"
    
end function

declare function sound alias "Beep" ( byval frequency as integer, byval duration as integer ) as integer

function _jsBEEP( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    
    if args.size = 0 then sound( 800, 700 ) : return "true"
    
    if args.size = 1 then
        dim as variable ptr check = varMap->find( args[0].strng )
        if check then
            sound( check->number, 1 )
            return "true"
        else
            sound( args[0].number, 1 )
            return "true"
        endif
    endif
    
    if args.size = 2 then
        dim as integer p1,p2
        dim as variable ptr check = varMap->find( args[0].strng )
        if check then
            p1 = check->number
        else
            p1 = args[0].number
        endif
        check = varMap->find( args[1].strng )
        if check then
            p2 = check->number
        else
            p2 = args[1].number
        endif
        
        sound( p1,p2 )
        return "true"
    endif
    
    return "false"
end function

function _jsbSLEEP( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    sleep : return "true"
end function

function _CLS( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    cls : return "true"
end function

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'                                                                               '
'                              Math Functions                                   '
'                                                                               '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

function _ADD( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    func_assert( args.size = 2, SYNTAX_ERROR, "Parameter count all wrong")
    
    for i as integer = 0 to 1
        if args[i].typ = varType._STRING_ then
            dim as variable ptr chk = varMap->find( args[i].strng )
            if chk then args[i] = *chk
        endif
    next i
    
    if args[0].typ = varType._NUMBER_ andalso args[1].typ = varType._NUMBER_ then
        return args[0].number + args[1].number
    else
        return DBLQUOTE + args[0].tostring + args[1].tostring + DBLQUOTE
    endif        
    
    return "null"
end function

function _SUB( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as double vRes
    
    if args[0].typ = varType._NUMBER_ then vRes = args[0].number
    if args[0].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[0].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[0].getType )
        vRes = check->number
    end if
    
    if args[1].typ = varType._NUMBER_ then vRes -= args[1].number
    if args[1].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[1].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[1].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[1].getType )
        vRes -= check->number
    end if
        
    return vRes
end function

function _MUL( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as double vRes
    
    if args[0].typ = varType._NUMBER_ then vRes = args[0].number
    if args[0].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[0].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[0].getType )
        vRes = check->number
    end if
    
    if args[1].typ = varType._NUMBER_ then vRes *= args[1].number
    if args[1].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[1].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[1].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[1].getType )
        vRes *= check->number
    end if
    
    return vRes
end function

function _DIV( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as double vRes
    
    if args[0].typ = varType._NUMBER_ then vRes = args[0].number
    if args[0].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[0].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[0].getType )
        vRes = check->number
    end if
    
    if args[1].typ = varType._NUMBER_ then vRes /= args[1].number
    if args[1].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[1].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[1].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[1].getType )
        vRes /= check->number
    end if
    
    return vRes
end function

function _MOD( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as double vRes
    
    if args[0].typ = varType._NUMBER_ then vRes = args[0].number
    if args[0].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[0].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[0].getType )
        vRes = check->number
    end if
    
    if args[1].typ = varType._NUMBER_ then vRes = vRes MOD args[1].number
    if args[1].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[1].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[1].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[1].getType )
        vRes = vRes MOD check->number
    end if
    
    return vRes
end function

function _EXP( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as double vRes
    
    if args[0].typ = varType._NUMBER_ then vRes = args[0].number
    if args[0].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[0].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[0].getType )
        vRes = check->number
    end if
    
    if args[1].typ = varType._NUMBER_ then vRes ^= args[1].number
    if args[1].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[1].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[1].strng )
        func_assert( check->getTypeNum = varType._NUMBER_, TYPE_MISMATCH, args[1].getType )
        vRes ^= check->number
    end if
    
    return vRes
end function

function _SIN( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as double vRes
    
    if args[0].typ = varType._NUMBER_ then return sin( args[0].number )
    if args[0].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[0].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[0].getType )
        vRes = check->number
    end if
    
    return sin( vRes )
end function

function _COS( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as double vRes
    
    if args[0].typ = varType._NUMBER_ then return cos( args[0].number )
    if args[0].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[0].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[0].getType )
        vRes = check->number
    end if
    
    return cos( vRes )
end function

function _TAN( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as double vRes
    
    if args[0].typ = varType._NUMBER_ then return tan( args[0].number )
    if args[0].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[0].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[0].getType )
        vRes = check->number
    end if
    
    return tan( vRes )
end function

function _ATAN( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as double vRes
    
    if args[0].typ = varType._NUMBER_ then return atn( args[0].number )
    if args[0].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[0].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[0].getType )
        vRes = check->number
    end if
    
    return atn( vRes )
end function

function _ATAN2( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    'Atan2(y,x)
    dim as double x,y
    
    if args[0].typ = varType._NUMBER_ then x = args[0].number
    if args[0].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[0].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[0].getType )
        y = check->number
    end if
    
    if args[1].typ = varType._NUMBER_ then y = args[1].number
    if args[1].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[1].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[1].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[1].getType )
        x = check->number
    end if
    
    return atan2( y, x )
end function

function _ACOS( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as double vRes
    
    if args[0].typ = varType._NUMBER_ then return acos( args[0].number )
    if args[0].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[0].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[0].getType )
        vRes = check->number
    end if
    
    return acos( vRes )
end function

function _ASIN( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as double vRes
    
    if args[0].typ = varType._NUMBER_ then return asin( args[0].number )
    if args[0].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[0].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[0].getType )
        vRes = check->number
    end if
    
    return asin( vRes )
end function

function _SQR( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as double vRes
    
    if args[0].typ = varType._NUMBER_ then return sqr( args[0].number )
    if args[0].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[0].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[0].getType )
        vRes = check->number
    end if
    
    return sqr( vRes )
end function

function _ABS( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as double vRes
    
    if args[0].typ = varType._NUMBER_ then return abs( args[0].number )
    if args[0].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[0].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[0].getType )
        vRes = abs( check->number )
    end if
    
    return vRes
end function

function _LOG( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as double vRes
    
    if args[0].typ = varType._NUMBER_ then return log( args[0].number )
    if args[0].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[0].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[0].getType )
        vRes = log( check->number )
    end if
    
    return vRes
end function

function _FIX( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as double vRes
    
    if args[0].typ = varType._NUMBER_ then return fix( args[0].number )
    if args[0].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[0].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[0].getType )
        vRes = fix( check->number )
    end if
    
    return vRes
end function

function _INT( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as double vRes
    
    if args[0].typ = varType._NUMBER_ then return int( args[0].number )
    if args[0].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[0].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[0].getType )
        vRes = int( check->number )
    end if
    
    return vRes
end function

function _FRAC( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as double vRes
    
    if args[0].typ = varType._NUMBER_ then return frac( args[0].number )
    if args[0].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[0].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[0].getType )
        vRes = frac( check->number )
    end if
    
    return vRes
end function

function _SGN( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as double vRes
    
    if args[0].typ = varType._NUMBER_ then return sgn( args[0].number )
    if args[0].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[0].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
        func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[0].getType )
        vRes = sgn( check->number )
    end if
    
    return vRes
end function

function _RND( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as double vRes
    
    return rnd
    
    if args.size then
        if args[0].typ = varType._NUMBER_ then return rnd * args[0].number
        if args[0].typ = varType._STRING_ then
            dim as variable ptr check = varMap->find( args[0].strng )
            func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
            func_assert( check->typ = varType._NUMBER_, TYPE_MISMATCH, args[0].getType )
            vRes = check->number*rnd
        end if
    endif
    
    return vRes
end function

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'                                                                               '
'                              String Functions                                 '
'                                                                               '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

function _CAT( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as string vRes
    
    dim as variable ptr check = varMap->find( args[0].strng )
    if check then
        vRes = check->toString
    else
        vRes = args[0].toString
    endif
    
    check = varMap->find( args[1].strng )
    if check then
        vRes += check->toString
    else
        vRes += args[1].toString
    endif

    return ascii(34)+vRes+ascii(34)
end function

function _LEN( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as integer vRes
    
    dim as variable ptr check = varMap->find( args[0].strng )
    if check then
        select case check->typ
        case varType._STRING_
            vRes = len( check->strng )
        case varType._ARRAY_
            vRes = check->getArray->size
        end select
    elseif args[0].typ = varType._STRING_ then
        vRes = len( args[0].strng )
    elseif args[0].typ = varType._ARRAY_ then
        vRes = args[0].array->size
    endif
    
    return vRes
end function

function _ASC( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as ubyte vRes 
    
    dim as variable ptr check = varMap->find( args[0].strng )
    if check then
        vRes = check->strng[0]
    else
        vRes = args[0].strng[0]
    endif
    
    return vRes
end function

function _CHR( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as string vRes = "" 
    
    dim as variable ptr check = varMap->find( args[0].strng )
    
    if check then
        vRes = ascii( check->number )
    else
        vRes = ascii( args[0].number )
    endif
    
    if vRes = "" then return ""
    return DBLQUOTE+vRes+DBLQUOTE
end function

function _LEFT( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as string p1 = "", vRes = ""
    dim as integer p2 = 0
    dim as variable arr
    
    func_assert( args.size = 2, ILLEGAL_FUNCTION_CALL, "Parameter count all wrong" )
    
    dim as variable ptr check = varMap->find( args[0].strng )
    dim as variable ptr checkNum = varMap->find( args[1].strng )
    
    if check = 0 then 
        check = new variable
        *check = args[0]
    endif
    
    if checkNum = 0 then 
        checkNum = new variable
        *checkNum = args[1]
    endif
    
    if check->typ = varType._STRING_ then
        p1 = check->strng
    elseif check->typ = varType._ARRAY_ then
        arr = *check
    endif

    p2 = args[1].number 
        
    
    if check->typ = varType._STRING_ then
        vRes = left( p1, p2 )
        return DBLQUOTE+vRes+DBLQUOTE
    elseif check->typ = varType._ARRAY_ then
        dim as variable vRes
        vRes.array = new varArray
        vRes.typ = varType._ARRAY_
        for i as integer = 0 to p2-1
            vRes.array->push_back( arr.array->items(i) )
        next i
        return vRes
    endif
end function

function _RIGHT( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as string p1 = "", vRes = ""
    dim as integer p2 = 0
    dim as variable arr
    
    func_assert( args.size = 2, ILLEGAL_FUNCTION_CALL, "Parameter count all wrong" )
    
    dim as variable ptr check = varMap->find( args[0].strng )
    dim as variable ptr checkNum = varMap->find( args[1].strng )
    
    if check = 0 then 
        check = new variable
        *check = args[0]
    endif
    
    if checknum = 0 then 
        checkNum = new variable
        *checkNum = args[1]
    endif
        
    if check->typ = varType._STRING_ then
        p1 = check->strng
    elseif check->typ = varType._ARRAY_ then
        arr = *check
    endif

    p2 = checkNum->number
    
    if check->typ = varType._STRING_ then
        vRes = right( p1, p2 )
        return DBLQUOTE+vRes+DBLQUOTE
    elseif check->typ = varType._ARRAY_ then
        dim as variable vRes
        vRes.array = new varArray
        vRes.typ = varType._ARRAY_
        for i as integer = p2 to arr.array->size-1
            vRes.array->push_back( arr.array->items(i) )
        next i
        return vRes
    endif
end function

function _MID( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as string p1 = ""
    dim as integer p2,p3
    dim as variable ptr check1,check2,check3
    dim as variable arr
    
    check1 = varMap->find( args[0].strng )
    check2 = varMap->find( args[1].strng )
    check3 = varMap->find( args[2].strng )
    
    if check1 then
        if check1->typ = varType._STRING_ then p1 = check1->strng
        if check1->typ = varType._ARRAY_ then arr = *check1
    else
        if args[0].typ = varType._STRING_ then p1 = args[0].strng
        if args[0].typ = varType._ARRAY_ then arr = args[0]
    endif
    
    if check2 then p2 = check2->number else p2 = args[1].number
    if check3 then p3 = check3->number else p3 = args[2].number
    
    if (check1 andalso check1->typ = varType._ARRAY_) orelse args[0].typ = varType._ARRAY_ then
        dim as integer p4 = p2+p3-1
        if p4 > arr.array->size-1 then p4 = arr.array->size-1
        dim as variable res
        res.array = new varArray
        res.typ = varType._ARRAY_
        for i as integer = p2-1 to p4-1
            res.array->push_back( arr.array->items(i) )
        next i
        return res
    else
        return DBLQUOTE+ mid(p1,p2,p3) +DBLQUOTE
    endif
    
    return "false"
end function

function _LCASE( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as string vRes = "" 
    
    dim as variable ptr check = varMap->find( args[0].strng )
    
    if check then
        vRes = check->strng
    else
        vRes = args[0].strng
    endif
    
    vRes = lcase( vRes )
    
    if vRes = "" then return ""
    return DBLQUOTE+vRes+DBLQUOTE
end function

function _UCASE( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as string vRes = "" 
    
    dim as variable ptr check = varMap->find( args[0].strng )
    
    if check then
        vRes = check->strng
    else
        vRes = args[0].strng
    endif
    
    vRes = ucase( vRes )
    
    if vRes = "" then return ""
    return DBLQUOTE+vRes+DBLQUOTE
end function

function _INSTR( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as integer vRes = 0
    dim as string p1 = "", p2 = ""
    dim as integer p3 = 1
    
    func_assert( args.size >= 2, ILLEGAL_FUNCTION_CALL, "Parameter count all wrong" )
    
    dim as variable ptr check = varMap->find( args[0].strng )
    
    if check then
        p1 = check->strng
    else
        p1 = args[0].strng
    endif
    
    check = 0
    check = varMap->find( args[1].strng )
    if check then
        p2 = check->strng
    else
        p2 = args[1].strng
    endif
    
    check = 0
    if args.size = 3 then
        check = varMap->find( args[2].strng )
        if check then
            p3 = check->number
        else
            p3 = args[2].number
        endif
    endif
    
    if p3 = 0 then p3 = 1
    
    vRes = instr( p3,p1,p2 )
    
    return vRes
end function

function _LOADFILEASSTRING( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as string vRes = "", p1 = ""

    dim as variable ptr check = varMap->find( args[0].strng )
    
    if check then
        p1 = check->strng
    else
        p1 = args[0].strng
    endif
    
    vRes = LoadFileAsString( p1 )
    dim as variable res 
    res.typ = varType._STRING_
    res.strng = vRes
    
    return res
end function

function _SPLIT( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    func_assert( args.size = 3, ILLEGAL_FUNCTION_CALL, "Parameter count all wrong" )
    
    dim as string txt = "", delim = ""
    dim as variable ptr check1 = varMap->find( args[0].strng )
    dim as variable ptr check2 = varMap->find( args[1].strng )
    dim as variable ptr check3 = varMap->find( args[2].strng )
    
    if check1 then txt = check1->strng else txt = args[0].strng
    if check2 then delim = check2->strng else delim = args[1].strng
    if check3 = 0 then check3 = @args[2]
    
    func_assert( check3, VARIABLE_NOT_DECLARED, args[2].strng )
    func_assert( len(delim) andalso len(txt), SYNTAX_ERROR, "Empty string" )
    
    txt &= ascii(delim[0])
    
    dim as integer nFields=0, bgn=0, lentxt = len(txt)-1
    dim as string newstring = ""
    
    for i as integer = 0 to lentxt
        for ii as integer = 0 to len(delim)-1
                if txt[i] = delim[ii] OR i = lentxt then
                    newstring = RIGHT ( LEFT ( txt, i ), i-bgn )
                    if newstring <> "" then
                        nFields+=1
                        dim as variable tmp = DBLQUOTE+newstring+DBLQUOTE
                        check3->array->push_back( @tmp )
                    endif
                    bgn = i+1
                endif
        next
    next
    return "true"
end function

function _SLICE( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    func_assert( args.size = 3, ILLEGAL_FUNCTION_CALL, "Parameter count all wrong" )
    dim as variable ptr check1 = varMap->find( args[0].strng )
    dim as variable ptr check2 = varMap->find( args[1].strng )
    dim as variable ptr check3 = varMap->find( args[2].strng )
    dim as integer idx1=0, idx2=0
    dim as string s = ""
    dim as variable arr
    
    if check1 then 
        if check1->typ = varType._STRING_ then s = check1->strng 
        if check1->typ = varType._ARRAY_ then arr = *check1
    else 
        if args[0].typ = varType._STRING_ then s = args[0].strng
        if args[0].typ = varType._ARRAY_ then arr = args[0]
    endif
    
    if check2 then idx1 = check2->number else idx1 = args[1].number
    if check3 then idx2 = check3->number else idx2 = args[2].number
    
    if s <> "" then
        dim as integer l = idx2-idx1
        return DBLQUOTE+ mid(s,idx1,l) +DBLQUOTE
    elseif arr.typ = varType._ARRAY_ then
        dim as variable res
        res.typ = varType._ARRAY_
        res.array = new varArray
        for i as integer = idx1 to idx2
            if i > arr.array->size-1 then exit for
            res.array->push_back( arr.array->items(i) )
        next i
        return res
    endif
end function

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'                                                                               '
'                               Array Functions                                 '
'                                                                               '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

function _PLUCK( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    dim as string vRes = ""
    dim as string p1 = ""
    dim as integer p2 = 0

    func_assert( args.size = 2, ILLEGAL_FUNCTION_CALL, "Parameter count all wrong" )
    
    dim as variable ptr check = varMap->find( args[0].strng )
    
    if check then
        if check->typ = varType._STRING_ then
            p1 = check->strng
        endif
        if check->typ = varType._ARRAY_ then
            dim as variable ptr check2 = varMap->find( args[1].strng )
            if check2 then
                dim as variable ptr pluck = check->array->get( check2->number )
                func_assert( pluck, ARRAY_OUT_OF_BOUNDS, check2->number )
                return *pluck
            else
                dim as variable ptr pluck = check->array->get( args[1].number )
                func_assert( pluck, ARRAY_OUT_OF_BOUNDS, args[1].number )
                return *pluck
            endif
        endif
        if check->typ = varType._OBJECT_ then
            dim as variable ptr check2 = varMap->find( args[1].strng )
            if check2 then
                dim as variable ptr pluck = check->object->get( check->strng )
                func_assert( pluck, INVALID_OBJECT_KEY, check2->strng )
                return *pluck
            else
                dim as variable ptr pluck = check->object->get( args[1].strng )
                func_assert( pluck, INVALID_OBJECT_KEY, args[1].strng )
                return *pluck
            endif
        endif
    else
        select case args[0].typ
        case varType._OBJECT_
            dim as variable ptr check2 = varMap->find( args[1].strng )
            dim as string obkey = ""
            if check2 then
                obkey = check2->strng
            else
                obkey = args[1].strng
            endif
            dim as variable ptr pluck = args[0].object->get( obkey )
            func_assert( pluck, INVALID_OBJECT_KEY, p2 )
            return *pluck
            
        case varType._ARRAY_
            dim as variable ptr check2 = varMap->find( args[1].strng )
            if check2 then 
                p2 = check2->number
            else 
                p2 = args[1].number
            endif
            dim as variable ptr pluck = args[0].array->get( p2 )
            func_assert( pluck, ARRAY_OUT_OF_BOUNDS, p2 )
            return *pluck
        case else
            'i dunno
        end select
        
    endif
    
    func_assert( p1 <> "", ILLEGAL_FUNCTION_CALL, "Empty string" )
    
    check = varMap->find( args[1].strng )
    
    if check then
        p2 = check->number
    else
        p2 = args[1].number
    endif
    
    func_assert( (p2 < len(p1) andalso p2 >= 0), ARRAY_OUT_OF_BOUNDS, p1 + "[" & p2 & "]" )
    
    return DBLQUOTE+ascii( p1[ p2 ] )+DBLQUOTE

end function

function _POP( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    func_assert( args.size = 2, ILLEGAL_FUNCTION_CALL, "Parameter count all wrong" )
    dim as variable ptr array_name = varMap->find( args[0].strng )
    dim as variable ptr check_idx = varMap->find( args[1].strng )
    dim as integer idx = 0
    
    if array_name = 0 then array_name = @args[0]
    
    if check_idx then
        func_assert( check_idx->typ = varType._NUMBER_, TYPE_MISMATCH, check_idx->lbl )
        idx = check_idx->number
    else
        func_assert( args[1].typ = varType._NUMBER_, TYPE_MISMATCH, args[1].lbl )
        idx = args[1].number
    endif
    
    array_name->array->pop( idx )
    
    return "true"
end function

function _PUSH( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    func_assert( args.size = 3, ILLEGAL_FUNCTION_CALL, "Parameter count all wrong" )
    dim as variable ptr array_name = varMap->find( args[0].strng )
    dim as variable ptr check_idx = varMap->find( args[1].strng )
    dim as variable ptr check_var = varMap->find( args[2].strng )
    dim as variable new_var
    
    dim as integer idx = 0

    if array_name = 0 then array_name = @args[0]
    
    if check_idx then
        func_assert( check_idx->typ = varType._NUMBER_, TYPE_MISMATCH, check_idx->lbl )
        idx = check_idx->number
    else
        func_assert( args[1].typ = varType._NUMBER_, TYPE_MISMATCH, args[1].lbl )
        idx = args[1].number
    endif
    
    if check_var then
        new_var = *check_var
    else
        new_var = args[2]
    endif

    array_name->getArray()->push( idx, @new_var )
    
    return "true"
end function

function _PUSH_BACK( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    func_assert( args.size = 2, ILLEGAL_FUNCTION_CALL, "Parameter count all wrong" )
    dim as variable ptr array_name = varMap->find( args[0].strng )
    dim as variable ptr add_var = varMap->find( args[1].strng )
    dim as integer idx = 0
    
    if array_name = 0 then array_name = @args[0]
    
    if add_var then
        array_name->array->push_back( add_var )
    else
        array_name->array->push_back( @args[1] )
    endif
    
    return "true"
end function

function _FIRST( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    func_assert( args.size = 1, ILLEGAL_FUNCTION_CALL, "Parameter count all wrong" )
    dim as variable ptr array_name = varMap->find( args[0].strng )
    if array_name = 0 then array_name = @args[0]
    func_assert( array_name->array->size, ARRAY_OUT_OF_BOUNDS, args[0].strng )
    return *array_name->array->items(0)
end function

function _LAST( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    func_assert( args.size = 1, ILLEGAL_FUNCTION_CALL, "Parameter count all wrong" )
    dim as variable ptr array_name = varMap->find( args[0].strng )
    if array_name = 0 then array_name = @args[0]
    func_assert( array_name->array->size, ARRAY_OUT_OF_BOUNDS, args[0].strng )
    return *array_name->array->items(  array_name->array->size - 1 )
end function

function _SIZE( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    func_assert( args.size = 1, ILLEGAL_FUNCTION_CALL, "Parameter count all wrong" )
    dim as variable ptr ob_name = varMap->find( args[0].strng )
    if ob_name = 0 then 
        func_assert( args[0].typ = varType._OBJECT_, ILLEGAL_FUNCTION_CALL, "Expected Object" )
        ob_name = @args[0]
    else
        func_assert( ob_name->typ = varType._OBJECT_, ILLEGAL_FUNCTION_CALL, "Expected Object" )
    endif
    return ob_name->object->size
end function

function _CLEAR( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    if args[0].typ = varType._STRING_ then
        dim as variable ptr check = varMap->find( args[0].strng )
        func_assert( check, VARIABLE_NOT_DECLARED, args[0].strng )
        check->array->clear
    elseif args[0].typ = varType._ARRAY_ then
        args[0].array->clear
    endif
    return "true"
end function

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'                                                                               '
'                              Bitwise Functions                                '
'                                                                               '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

function _ISEQUAL( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    func_assert( args.size = 2, ILLEGAL_FUNCTION_CALL, "Parameter count all wrong" )
    
    dim as variable ptr check1 = varMap->find( args[0].strng )
    dim as variable ptr check2 = varMap->find( args[1].strng )
    dim as variable p1,p2
    
    if check1 then p1 = *check1 else p1 = args[0]
    if check2 then p2 = *check2 else p2 = args[1]
    
    if p1.typ <> p2.typ then return "false"
    
    select case p1.typ
    case varType._STRING_
        if p1.strng = p2.strng then return "true"
    case varType._NUMBER_
        if p1.number = p2.number then return "true"
    case varType._BOOL_
        if p1.bool = p2.bool then return "true"
    end select
    
    return "false"
end function

function _GREATERTHAN( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    func_assert( args.size = 2, ILLEGAL_FUNCTION_CALL, "Parameter count all wrong" )
    
    dim as variable ptr check1 = varMap->find( args[0].strng )
    dim as variable ptr check2 = varMap->find( args[1].strng )
    dim as variable p1,p2
    
    if check1 then p1 = *check1 else p1 = args[0]
    if check2 then p2 = *check2 else p2 = args[1]
    
    if p1.typ <> p2.typ then return "false"
    
    select case p1.typ
    case varType._STRING_ : if strcmp( p1.strng, p2.strng ) = 1 then return "true" else return "false"
    case varType._NUMBER_ : if p1.number > p2.number then return "true" else return "false"
    case varType._BOOL_   : if p1.bool > p2.bool then return "true" else return "false"
    end select
    
    return "false"
end function

function _LESSTHAN( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    func_assert( args.size = 2, ILLEGAL_FUNCTION_CALL, "Parameter count all wrong" )
    
    dim as variable ptr check1 = varMap->find( args[0].strng )
    dim as variable ptr check2 = varMap->find( args[1].strng )
    dim as variable p1,p2
    
    if check1 then p1 = *check1 else p1 = args[0]
    if check2 then p2 = *check2 else p2 = args[1]
    
    if p1.typ <> p2.typ then return "false"
    
    select case p1.typ
    case varType._STRING_ : if strcmp( p1.strng, p2.strng ) = -1 then return "true" else return "false"        
    case varType._NUMBER_ : if p1.number < p2.number then return "true" else return "false"
    case varType._BOOL_   : if p1.bool < p2.bool then return "true" else return "false"
    end select
    
    return "false"
end function

function _GTEQ( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    func_assert( args.size = 2, ILLEGAL_FUNCTION_CALL, "Parameter count all wrong" )
    
    dim as variable ptr check1 = varMap->find( args[0].strng )
    dim as variable ptr check2 = varMap->find( args[1].strng )
    dim as variable p1,p2
    
    if check1 then p1 = *check1 else p1 = args[0]
    if check2 then p2 = *check2 else p2 = args[1]
    
    if p1.typ <> p2.typ then return "false"
    
    select case p1.typ
    case varType._STRING_ : if strcmp( p1.strng, p2.strng ) >= 0 then return "true"
    case varType._NUMBER_ : if p1.number >= p2.number then return "true"
    case varType._BOOL_   : if p1.bool >= p2.bool then return "true"
    end select
    
    return "false"
end function

function _LTEQ( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    func_assert( args.size = 2, ILLEGAL_FUNCTION_CALL, "Parameter count all wrong" )
    
    dim as variable ptr check1 = varMap->find( args[0].strng )
    dim as variable ptr check2 = varMap->find( args[1].strng )
    dim as variable p1,p2
    
    if check1 then p1 = *check1 else p1 = args[0]
    if check2 then p2 = *check2 else p2 = args[1]
    
    if p1.typ <> p2.typ then return "false"
    
    select case p1.typ
    case varType._STRING_ : if strcmp( p1.strng, p2.strng ) <= 0 then return "true"        
    case varType._NUMBER_ : if p1.number <= p2.number then return "true"        
    case varType._BOOL_   : if p1.bool <= p2.bool then return "true"        
    end select
    
    return "false"
end function

function _UNEQUAL( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    func_assert( args.size = 2, ILLEGAL_FUNCTION_CALL, "Parameter count all wrong" )
    
    dim as variable ptr check1 = varMap->find( args[0].strng )
    dim as variable ptr check2 = varMap->find( args[1].strng )
    dim as variable p1,p2
    
    if check1 then p1 = *check1 else p1 = args[0]
    if check2 then p2 = *check2 else p2 = args[1]
    
    if p1.typ <> p2.typ then return "true"
    
    select case p1.typ
    case varType._STRING_
        if p1.strng = p2.strng then return "false"
    case varType._NUMBER_
        if p1.number = p2.number then return "false"
    case varType._BOOL_
        if p1.bool = p2.bool then return "false"
    end select
    
    return "true"
end function

function _NOT( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    func_assert( args.size = 1, ILLEGAL_FUNCTION_CALL, "Parameter count all wrong" )
    
    dim as variable ptr check1 = varMap->find( args[0].strng )
    dim as variable p1
    
    if check1 then p1 = *check1 else p1 = args[0]
    
    select case p1.typ
    case varType._NUMBER_
        return not( p1.number )
    case varType._BOOL_
        if p1.bool = JSON_BOOL._TRUE_ then return "false" else return "true"
    case else
        func_assert( 0, TYPE_MISMATCH, p1.toString )
    end select
    
end function

function _AND( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    for i as integer = 0 to args.size-1
        if args[i].bool = JSON_BOOL._FALSE_ then return "false"
    next i
    return "true"
end function

function _OR( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    for i as integer = 0 to args.size-1
        if args[i].bool = JSON_BOOL._TRUE_ then return "true"
    next i
    return "false"
end function

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'                                                                               '
'                              Parsing Functions                                '
'                                                                               '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

function _TYPEOF( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
    func_assert( args.size = 1, ILLEGAL_FUNCTION_CALL, "Parameter count all wrong" )
    
    dim as variable ptr check1 = varMap->find( args[0].strng )
    
    if check1 then
        return DBLQUOTE+ check1->getType +DBLQUOTE
    else
        return DBLQUOTE+ args[0].getType +DBLQUOTE
    endif
end function

Last edited by rolliebollocks on Jul 10, 2014 2:20, edited 7 times in total.
rolliebollocks
Posts: 2655
Joined: Aug 28, 2008 10:54
Location: new york

Re: json basic scripting language

Post by rolliebollocks »

jsb_context.bas

Code: Select all

#include once "jsb_function.bas"
#include once "jsb_functions.bas"
#include once "jsb_varmap.bas"
#include once "jsb_lexer.bas"

type jsb_context
    
    Public:
        declare Constructor()
        declare Destructor()
        declare Constructor( byref rhs as jsb_context )
        declare Operator Let( byref rhs as jsb_context )
               
        declare function searchVar( byval lbl as string ) as variable ptr
        declare function searchFunc( byval lbl as string ) as jsb_function ptr
        declare function searchUser( byval lbl as string ) as jsb_user_func ptr
        
        declare sub initScript( byval s as string )
        declare sub setScope( byval i as integer )
        declare sub addScope()
        
        declare sub clear()
    
        as jsb_var_map          variables
        as jsb_function_map     jsb_functions
        as token_array          script
        as jsb_user_func_ctx    user_funcs                
        as integer              curScope
        
        as string               out_string
        
end type

sub jsb_context.clear()
    variables.clear
    script.clear
    user_funcs.user_funcs.clear
    curScope = 0
    variables.vars.resize( 1 )
end sub

Constructor jsb_context
end Constructor

Destructor jsb_context()
    for i as integer = 0 to user_funcs.user_funcs.size-1
        delete user_funcs.user_funcs[i].head
        delete user_funcs.user_funcs[i].body
    next i
end Destructor


Constructor jsb_context( byref rhs as jsb_context )
    this.jsb_functions = rhs.jsb_functions
    this.script = rhs.script
    this.variables = rhs.variables
    this.user_funcs = rhs.user_funcs
    this.curScope = rhs.curScope
end Constructor

Operator jsb_context.Let( byref rhs as jsb_context )
    if @this = @rhs then exit Operator
    this.jsb_functions = rhs.jsb_functions
    this.script = rhs.script
    this.variables = rhs.variables
    this.user_funcs = rhs.user_funcs
    this.curScope = rhs.curScope
end Operator

function jsb_context.searchVar( byval lbl as string ) as variable ptr           
    return variables.find( lbl )
end function

function jsb_context.searchFunc( byval lbl as string ) as jsb_function ptr
    return jsb_functions.find( lbl )
end function

function jsb_context.searchUser( byval lbl as string ) as jsb_user_func ptr
    return user_funcs.find( lbl )
end function

sub jsb_context.initScript( byval s as string )
    this.script.init( s )
    if user_func_ctx.user_funcs.size <> 0 then
        this.user_funcs = user_func_ctx
    endif
end sub

sub jsb_context.setScope( byval i as integer )
    this.curScope = i
    this.variables.curScope = i
end sub

sub jsb_context.addScope()
    this.variables.vars.resize( this.variables.vars.size+1 )
end sub

dim shared as jsb_context context

sub InitializeFunctions( byref context as jsb_context )
    '%f = function name
    '%v = variable name
    '%a = any
    '%m = math operator
    
    'variable assignment
    context.jsb_functions.add( "var",       @_VAR,          "%f %v = %a"    )
    context.jsb_functions.add( "=",         @_ASSIGN,       "%v = %a"       )
    'misc
    context.jsb_functions.add( "print",     @_PRINT,        "%f(%a)"        )
    context.jsb_functions.add( "beep",      @_jsBEEP,       "%f(%a,%a)"     )
    context.jsb_functions.add( "sleep",     @_jsbSLEEP,     "%f"            )
    context.jsb_functions.add( "cls",       @_CLS,          "%f"            )
    'math
    context.jsb_functions.add( "+",         @_ADD,          "%a %m %a"      )
    context.jsb_functions.add( "-",         @_SUB,          "%a %m %a"      )
    context.jsb_functions.add( "*",         @_MUL,          "%a %m %a"      )
    context.jsb_functions.add( "/",         @_DIV,          "%a %m %a"      )
    context.jsb_functions.add( "^",         @_EXP,          "%a %m %a"      )
    context.jsb_functions.add( "%",         @_MOD,          "%a %m %a"      )
    context.jsb_functions.add( "mod",       @_MOD,          "%a %f %a"      )
    context.jsb_functions.add( "sin",       @_SIN,          "%f(%a)"        )
    context.jsb_functions.add( "cos",       @_COS,          "%f(%a)"        )
    context.jsb_functions.add( "tan",       @_TAN,          "%f(%a)"        )
    context.jsb_functions.add( "asin",      @_ASIN,         "%f(%a)"        )
    context.jsb_functions.add( "acos",      @_ACOS,         "%f(%a)"        )
    context.jsb_functions.add( "atn",       @_ATAN,         "%f(%a)"        )
    context.jsb_functions.add( "atan2",     @_ATAN2,        "%f(%a,%a)"     )
    context.jsb_functions.add( "sqr",       @_SQR,          "%f(%a)"        )
    context.jsb_functions.add( "abs",       @_ABS,          "%f(%a)"        )
    context.jsb_functions.add( "log",       @_LOG,          "%f(%a)"        )
    context.jsb_functions.add( "fix",       @_FIX,          "%f(%a)"        )
    context.jsb_functions.add( "int",       @_INT,          "%f(%a)"        )
    context.jsb_functions.add( "frac",      @_FRAC,         "%f(%a)"        )
    context.jsb_functions.add( "sgn",       @_SGN,          "%f(%a)"        )
    context.jsb_functions.add( "rnd",       @_RND,          "%f(%a)"        )
    'basic string functions
    context.jsb_functions.add( "len",       @_LEN,          "%f(%a)"        )
    context.jsb_functions.add( "asc",       @_ASC,          "%f(%a)"        )
    context.jsb_functions.add( "chr",       @_CHR,          "%f(%a)"        )
    context.jsb_functions.add( "left",      @_LEFT,         "%a.%f(%a)"     )
    context.jsb_functions.add( "right",     @_RIGHT,        "%a.%f(%a)"     )
    context.jsb_functions.add( "mid",       @_MID,          "%a.%f(%a,%a)"  )
    context.jsb_functions.add( "lcase",     @_LCASE,        "%a.%f"         )
    context.jsb_functions.add( "ucase",     @_UCASE,        "%a.%f"         ) 
    context.jsb_functions.add( "instr",     @_INSTR,        "%f(%a,%a,%a)"  ) 
    'extended string functions
    context.jsb_functions.add( "load_file_as_string",     @_LOADFILEASSTRING,        "%f(%a)"  ) 
    context.jsb_functions.add( "split",     @_SPLIT,        "%a.%f(%a,%a)"  )
    context.jsb_functions.add( "slice",     @_SLICE,        "%a.%f(%a,%a)"  )
    'array
    context.jsb_functions.add( "pluck",     @_PLUCK,        "%f(%a,%a)"     ) 
    context.jsb_functions.add( "length",    @_LEN,          "%a.%f"         )
    context.jsb_functions.add( "pop",       @_POP,          "%v.%f(%a)"     )
    context.jsb_functions.add( "push",      @_PUSH,         "%v.%f(%a,%a)"  )
    context.jsb_functions.add( "push_back", @_PUSH_BACK,    "%v.%f(%a)"     )
    context.jsb_functions.add( "first",     @_FIRST,        "%v.%f"         )
    context.jsb_functions.add( "last",      @_LAST,         "%v.%f"         )
    context.jsb_functions.add( "clear",     @_CLEAR,        "%v.%f"         )
    'object
    context.jsb_functions.add( "size",      @_SIZE,         "%v.%f"         )
    'bitwise
    context.jsb_functions.add( "==",        @_ISEQUAL,      "%v %f %v"      )
    context.jsb_functions.add( "!=",        @_UNEQUAL,      "%v %f %v"      )
    context.jsb_functions.add( "<>",        @_UNEQUAL,      "%v %f %v"      )
    context.jsb_functions.add( ">",         @_GREATERTHAN,  "%v %f %v"      )
    context.jsb_functions.add( "<",         @_LESSTHAN,     "%v %f %v"      )
    context.jsb_functions.add( ">=",        @_GTEQ,         "%v %f %v"      )
    context.jsb_functions.add( "<=",        @_LTEQ,         "%v %f %v"      )
    context.jsb_functions.add( "&&",        @_AND,          "<>"            )
    context.jsb_functions.add( "and",       @_AND,          "<>"            )
    context.jsb_functions.add( "or",        @_OR,           "<>"            )
    context.jsb_functions.add( "||",        @_OR,           "<>"            )
    'Parsing
    context.jsb_functions.add( "typeof",    @_TYPEOF,       "%f(%a)"        )
    
    
end sub

InitializeFunctions( context )

Last edited by rolliebollocks on Jul 10, 2014 2:21, edited 6 times in total.
rolliebollocks
Posts: 2655
Joined: Aug 28, 2008 10:54
Location: new york

Re: json basic scripting language

Post by rolliebollocks »

jsb_parser.bas

Code: Select all

#include once "jsb_context.bas"

declare function Parse( byref inScript as token_array ) as variable
declare function Eval( byref _inExpr as token_array ) as variable

function lineCount( byref tk as token_array ) as integer
    dim as integer res = 0, braceOpen = 0
   
    for i as integer = 0 to tk.tokens.size-1
        if tk.tokens[i].myType = _OPEN_CBRACE_ then braceOpen += 1
        if tk.tokens[i].myType = _CLOSE_CBRACE_ then braceOpen -= 1
        if braceOpen = 0 then
            if tk.tokens[i].myType = _END_LINE_ then res += 1
        endif
    next i
   
    if res = 0 then res = 1
   
    return res
end function

function getLine( byval lineNum as integer, byref tk as token_array ) as token_array
    dim as token_array res
    dim as integer line_count = lineCount( tk )
    if lineNum > line_count then return res
    dim as integer curLine = 1, braceOpen = 0
   
    for i as integer = 0 to tk.tokens.size - 1
        if curLine = lineNum then
            res.tokens.push_back( tk.tokens[i] )
        endif
        if curLine > lineNum orelse curLine > tk.tokens.size - 1 then exit for
        if tk.tokens[i].myType = _OPEN_CBRACE_ then braceOpen += 1
        if tk.tokens[i].myType = _CLOSE_CBRACE_ then braceOpen -= 1
        if braceOpen = 0 then
            if tk.tokens[i].myType = _END_LINE_ then curline += 1
        endif
    next i
    return res
end function

function countParens( byref tk as token_array ) as integer
    dim as integer pidx = tk.find( _OPEN_PAREN_ )
    if pidx = -1 then return 0
    if pidx = tk.tokens.size-1 then return -1
    if tk.tokens[pidx+1].myType = _CLOSE_PAREN_ then return 0
    dim as integer lcount = 0, rcount = 0
    for i as integer = 0 to tk.tokens.size-1
        select case tk.tokens[i].myType
        case _OPEN_PAREN_ : lcount += 1
        case _CLOSE_PAREN_ : rcount += 1
        end select
    next i
    if lcount = rcount then return lcount
    return -1
end function

function countParameters( byref tk as token_array ) as integer
    if tk.find( _FUNCTION_ ) = -1 andalso tk.find( _USER_FUNC_ ) = -1 then return 0
    dim as integer pidx = tk.find( _OPEN_PAREN_ )
    if pidx = -1 andalso tk.tokens.size = 1 then return 0
    if pidx = tk.tokens.size-1 then return 0
    if tk.tokens[ pidx+1 ].myType = _CLOSE_PAREN_ then return 0
    dim as integer count = 0
    for i as integer = 0 to tk.tokens.size - 1
        if tk.tokens[i].myType = token_typ._COMMA_ then
            count += 1
        endif
    next i
   
    return count + 1
end function        

function countBraces( byref tk as token_array ) as integer
    dim as integer lcount = 0, rcount = 0
    for i as integer = 0 to tk.tokens.size-1
        select case tk.tokens[i].myType
        case _OPEN_BRACE_ : lcount += 1
        case _CLOSE_BRACE_ : rcount += 1
        end select
    next i
    if lcount = rcount then return lcount
    return -1
end function

function getParenExpr( byref tk as token_array, byval idx as integer ) as token_array
    dim as integer nExpr = countParens( tk )
    dim as token_array res
   
    if idx = 0 then
        if tk.tokens.back->myType = _END_LINE_ then
            return cut_left( tk, tk.tokens.size-2 )
        else
            return tk
        endif
    endif
       
    if idx > nExpr then return res
    if idx < 0 then return res
    dim as integer curLevel, rLevel, lLevel, i, done

    Do
       
        if tk.tokens[i].myType = _OPEN_PAREN_ then curLevel += 1
       
        if curLevel = idx then
           
            Do
               
                if tk.tokens[i].myType = _CLOSE_PAREN_ then 
                    rlevel += 1
                    if rlevel <> llevel then res.tokens.push_back( tk.tokens[i] )
                elseif tk.tokens[i].myType = _OPEN_PAREN_ then 
                    lLevel += 1
                    if llevel <> 1 then res.tokens.push_back( tk.tokens[i] )
                else
                    res.tokens.push_back( tk.tokens[i] )
                endif
                if lLevel = rLevel then done = 1 : exit do                
                i+= 1
                
            loop until done = 1
           
        endif
       
        i += 1
       
    loop until done = 1
   
    return res
end function

function getBraceExpr( byref tk as token_array, byval idx as integer ) as token_array
    dim as integer nExpr = countBraces( tk )
    dim as token_array res
   
    if idx = 0 then
        if tk.tokens.back->myType = _END_LINE_ then
            return cut_left( tk, tk.tokens.size-2 )
        else
            return tk
        endif
    endif
       
    if idx > nExpr then return res
    if idx < 0 then return res
    dim as integer curLevel, rLevel, lLevel, i, done

    Do
       
        if tk.tokens[i].myType = _OPEN_BRACE_ then curLevel += 1
       
        if curLevel = idx then
           
            Do
               
                if tk.tokens[i].myType = _CLOSE_BRACE_ then 
                    rlevel += 1
                    if rlevel <> llevel then res.tokens.push_back( tk.tokens[i] )
                elseif tk.tokens[i].myType = _OPEN_BRACE_ then 
                    lLevel += 1
                    if llevel <> 1 then res.tokens.push_back( tk.tokens[i] )
                else
                    res.tokens.push_back( tk.tokens[i] )
                endif
                if lLevel = rLevel then done = 1 : exit do                
                i+= 1
                
            loop until done = 1
           
        endif
       
        i += 1
       
    loop until done = 1
   
    return res
end function

function getParam( byref tk as token_array, byval idx as integer ) as token_array
    dim as integer count = 0, i = 0
    dim as token_array res
   
    Do while count <> idx
        if count = idx - 1 then
            if tk.tokens[i].myType <> token_typ._COMMA_ then
                if tk.tokens[i].myType <> token_typ._OPEN_PAREN_ andalso _
                   tk.tokens[i].myType <> token_typ._CLOSE_PAREN_ then
                    res.tokens.push_back( tk.tokens[i] )
                endif
            endif
        endif
        if tk.tokens[i].myType = token_typ._COMMA_ then count += 1
        i += 1
        if i > tk.tokens.size - 1 then exit do
    Loop
   
    return res
end function

function opCompare( byref tk1 as token_array, byref tk2 as token_array ) as integer
    dim as token ptr t1 = tk1.findPtr( _MATHOP_ )
    dim as token ptr t2 = tk2.findPtr( _MATHOP_ )
   
    select case t1->value.toString
    case "^"
        if t2->value.toString = "^" then return 0 else return -1
    case "*"
        if t2->value.toString = "^" then
            return 1
        elseif t2->value.toString = "*" then
            return 0
        else
            return -1
        endif
    case "/"
        if t2->value.toString = "^" orelse t2->value.toString = "*" then
            return 1
        elseif t2->value.toString = "/" then
            return 0
        else
            return -1
        endif
    case "+"
        if t2->value.toString = "^" orelse t2->value.toString = "*" orelse t2->value.toString = "/" then
            return 1
        elseif t2->value.toString = "+" then
            return 0
        else
            return -1
        endif
    case "-"
        if t2->value.toString = "-" then
            return 0
        else
            return 1
        endif
    end select
       
    return -666
end function


'==============================================================================='
#DEFINE DBLQUOTE ascii(34)

function EatVars( byref inLine as token_array ) as token_array
    dim as token_array res
   
    for i as integer = 0 to inLine.tokens.size-1
        if inLine.tokens[i].myType = token_typ._VAR_NAME_ then
            dim as variable ptr chk1 = context.searchVar( inLine.tokens[i].value.strng )
            if chk1 then
                if chk1->typ = varType._ARRAY_ orelse chk1->typ = varType._OBJECT_ then
                   
                    if i < inLine.tokens.size-2 then
                        if inLine.tokens[i+1].myType <> _DOT_ then
                            dim as jsb_function ptr j = context.searchFunc( "pluck" )
                            dim as vectorVariable args
                            args.push_back( inLine.tokens[i].value )
                            args.push_back( inLine.tokens[i+2].value )
                            dim as variable tmp = j->func( @context.variables, args )
                            if tmp.typ = varType._STRING_ then
                                dim as token t
                                t.myType = _DBL_QUOTE_
                                res.tokens.push_back( t )
                                res.tokens.push_back( tmp )
                                res.tokens.push_back( t )
                            elseif tmp.typ = varType._ARRAY_ then
                                res.tokens.push_back( tmp )
                                res = EatVars( res )
                            else
                                res.tokens.push_back( tmp )
                            endif
                            i+=3
                        else
                            res.tokens.push_back( inLine.tokens[i] )
                        endif
                    else
                        res.tokens.push_back( inLine.tokens[i] )
                    endif
                else
                    if chk1->typ = varType._STRING_ then
                        dim as token t
                        t.myType = _DBL_QUOTE_
                        res.tokens.push_back( t )
                        res.tokens.push_back( *chk1 )
                        res.tokens.push_back( t )
                    else
                        res.tokens.push_back( *chk1 )
                    endif
                endif
            else
                res.tokens.push_back( inLine.tokens[i] )
            endif
        else
            res.tokens.push_back( inLine.tokens[i] )
        endif
    next i

    return res
end function

function Eval( byref _inExpr as token_array ) as variable
    dim as variable res
   
    if _inExpr.tokens.size = 0 then return "false"
   
    dim as token_array inExpr = _inExpr

    #define call_func res = inFunc->func( @context.variables, args )
   
    #macro build_args( start, nargs )
        if nargs <> 0 then
            dim as integer c = 0
            args.resize( nargs )
            for i as integer = start to inExpr.tokens.size-1
                select case inExpr.tokens[i].myType
                case token_typ._VAR_NAME_ : args[c] = inExpr.tokens[i].value : c+=1
                case token_typ._STRING_   : args[c] = inExpr.tokens[i].value : c+=1
                case token_typ._NUMBER_   : args[c] = inExpr.tokens[i].value : c+=1
                case token_typ._BOOL_     : args[c] = inExpr.tokens[i].value : c+=1
                case token_typ._ARRAY_    : args[c] = inExpr.tokens[i].value : c+=1
                case token_typ._OBJECT_   : args[c] = inExpr.tokens[i].value : c+=1
                case token_typ._TRUE_     : args[c] = inExpr.tokens[i].value : c+=1
                case token_typ._FALSE_    : args[c] = inExpr.tokens[i].value : c+=1
                end select
                if c = nargs then exit for
            next i
        endif
    #endmacro
   
    #macro eq_compare( s )
        dim as vectorVariable args
        dim as jsb_function ptr inFunc = context.searchFunc( s )
        build_args( 0,2 )
        call_func
    #endmacro

    #macro check_eq()
    Scope
        dim as integer idx = -1
        idx = inExpr.find( _EQUAL_COMPARE_ )
        if idx <> -1 then
            eq_compare( "==" )
        endif
        idx = inExpr.find( _GREATER_THAN_ )
        if idx <> -1 then
            eq_compare( ">" )
        endif
        idx = inExpr.find( _LESS_THAN_ )
        if idx <> -1 then
            eq_compare( "<" )
        endif
        idx = inExpr.find( _EQUAL_OR_GREATER_ )
        if idx <> -1 then
            eq_compare( "<=" )
        endif
        idx = inExpr.find( _EQUAL_OR_LESS_ )
        if idx <> -1 then
            eq_compare( ">=" )
        endif
        idx = inExpr.find( _NOT_EQUAL_ )
        if idx <> -1 then
            eq_compare( "!=" )
        endif
    End Scope
    #endmacro
   
    #macro call_afa()
        Scope
            dim as vectorVariable args
            build_args( 0,2 )
            call_func
            check_rest( 3 )
        end Scope
    #endmacro
   
    #macro check_rest( n )
        if inExpr.tokens.size > n andalso n <> 0 then
            dim as token_array rest = cut_right( inExpr, n )
            dim as token t
            select case res.typ
            case varType._OBJECT_ : rest.tokens.insert( 0, res )
            case varType._ARRAY_  : rest.tokens.insert( 0, res )
            case varType._NUMBER_ : rest.tokens.insert( 0, res )
            case varType._STRING_
                rest.tokens.insert( 0, res )
            case varType._BOOL_
                rest.tokens.insert( 0, res )
            end select
            res = Eval( rest )
        endif
    #endmacro

    #macro handle_object( _varptr )  
    Scope
        dim as integer idx = inExpr.find( _MATHOP_ )
        if idx <> -1 andalso inExpr.tokens[idx+1].myType <> _EQUAL_ASSIGN_ then
            dim as token_array lhs = cut_left( inExpr, idx-1 )
            dim as token_array rhs = cut_right( inExpr, idx+1 )
            res = Eval( lhs )
            dim as vectorVariable args
            args.push_back( res )
            res = Eval( rhs )
            args.push_back( res )
            dim as jsb_function ptr inFunc = context.searchFunc( inExpr.tokens[idx].value.strng )
            call_func
            return res
        elseif idx <> -1 andalso inExpr.tokens[idx+1].myType = _EQUAL_ASSIGN_ then
            dim as vectorVariable args
            dim as token_array lhs = cut_left( inExpr, idx-1 )
            dim as token_array rhs = cut_right( inExpr, idx+2 )
            res = Eval( lhs )
            args.push_back( res )
            res = Eval( rhs )
            args.push_back( res )
            res = context.searchFunc( inExpr.tokens[idx].value.strng )->func( @context.variables, args )
            args.clear
            args.push_back( inExpr.tokens[0].value )
            args.push_back( inExpr.tokens[2].value )
            args.push_back( res )
            res = context.searchFunc( "=" )->func( @context.variables, args )
        endif
       
        if (inExpr.tokens[1].myType = _OPEN_BRACE_ orelse inExpr.tokens[1].myType = _DOT_) _
            andalso inExpr.tokens[2].myType <> _FUNCTION_ then
            dim as jsb_function ptr inFunc = context.searchFunc( "pluck" )
            dim as vectorVariable args
            build_args(0,2)
            call_func
            if res.typ = varType._ARRAY_ then
                dim as token_array expr = cut_right( inExpr, 4 )
                expr.tokens.insert( 0, res )
                res = Eval( expr )
                exit select
            elseif res.typ = varType._OBJECT_ then
                dim as token_array expr = cut_right( inExpr, 4 )
                expr.tokens.insert( 0, res )
                res = Eval( expr )
                exit select
            elseif inExpr.tokens.size = 3 then
                return res
            endif
        endif

        check_eq()
       
        if inExpr.find( _EQUAL_ASSIGN_ ) <> -1 then
            dim as variable ptr obj = _varptr
            dim as vectorVariable args
            build_args( 1, 2 )
            dim as variable ptr objfield = obj->object->get( args[0].strng )
            parse_assert( objfield, INVALID_OBJECT_KEY, -1, args[0].strng )
            *objfield = args[1]
            res = "true"
        endif
       
        idx = inExpr.find( _DOT_ )
        if idx <> -1 andalso inExpr.tokens.size-idx > 0 andalso inExpr.tokens[idx+1].myType = _FUNCTION_ then
            dim as jsb_function ptr inFunc = context.searchFunc( inExpr.tokens[idx+1].value.strng )
            parse_assert( inFunc, NO_SUCH_FUNCTION, 0, inExpr.tokens[idx+1].value.strng )
            select case inFunc->signature
                case "%v.%f(%a,%a)", "%a.%f(%a,%a)"
                    dim as vectorVariable args
                    build_args( 0,3 )
                    call_func
                    return res
                case "%v.%f(%a)", "%a.%f(%a)"
                    dim as vectorVariable args
                    build_args( 0,2 )
                    call_func
                    return res
                case "%v.%f", "%a.%f"
                    dim as vectorVariable args
                    build_args( 0,1 )
                    call_func
                    return res
            end select
        endif
       
    end Scope
    #endmacro

    #macro check_assign()
        if inExpr.find( _EQUAL_ASSIGN_ ) <> -1 then
            dim as vectorVariable args
            build_args( 1,2 )
            with inExpr.tokens[0]
                dim as variable ptr arr = @.value
            end with
            dim as variable ptr arrfield = arr->array->get( args[0].number )
            parse_assert( arrfield, ARRAY_OUT_OF_BOUNDS, -1, args[0].number )
            *arrfield = args[1]
            res = "true"
        endif
    #endmacro

    #macro handle_array(_varptr)
    Scope
        dim as integer idx = inExpr.find( _MATHOP_ )
        if idx <> -1 andalso inExpr.tokens[idx+1].myType <> _EQUAL_ASSIGN_ then
            dim as token_array lhs = cut_left( inExpr, idx-1 )
            dim as token_array rhs = cut_right( inExpr, idx+1 )
            res = Eval( lhs )
            dim as vectorVariable args
            args.push_back( res )
            res = Eval( rhs )
            args.push_back( res )
            dim as jsb_function ptr inFunc = context.searchFunc( inExpr.tokens[idx].value.strng )
            call_func
            return res
        elseif idx <> -1 andalso inExpr.tokens[idx+1].myType = _EQUAL_ASSIGN_ then
            dim as vectorVariable args
            dim as token_array lhs = cut_left( inExpr, idx-1 )
            dim as token_array rhs = cut_right( inExpr, idx+2 )
            res = Eval( lhs )
            args.push_back( res )
            res = Eval( rhs )
            args.push_back( res )
            res = context.searchFunc( inExpr.tokens[idx].value.strng )->func( @context.variables, args )
            args.clear
            args.push_back( inExpr.tokens[0].value )
            args.push_back( inExpr.tokens[2].value )
            args.push_back( res )
            res = context.searchFunc( "=" )->func( @context.variables, args )
            return res
        endif
       
        if inExpr.tokens[1].myType = _OPEN_BRACE_ then
            dim as jsb_function ptr inFunc = context.searchFunc( "pluck" )
            dim as vectorVariable args
            build_args(0,2)
            call_func
            if res.typ = varType._ARRAY_ then
                dim as token_array expr = cut_right( inExpr, 4 )
                expr.tokens.insert( 0, res )
                res = Eval( expr )
                inExpr = expr
                check_assign()
            elseif res.typ = varType._OBJECT_ then
                dim as token_array expr = cut_right( inExpr, 4 )
                expr.tokens.insert( 0, res )
                res = Eval( expr )
            elseif inExpr.tokens.size = 4 then
                return res
                exit select
            else
                dim as token_array expr = cut_right( inExpr, 4 )
                expr.tokens.insert( 0, res )
                res = Eval( expr )
                return res
            endif
        endif
       
        check_eq()
        
        idx = inExpr.find( _DOT_ )
        if idx <> -1 andalso inExpr.tokens.size-idx > 0 andalso inExpr.tokens[idx+1].myType = _FUNCTION_ andalso _ 
        ( res.typ = varType._ARRAY_ orelse res.typ = varType._OBJECT_ orelse res.typ = 0 ) then
            dim as jsb_function ptr inFunc = context.searchFunc( inExpr.tokens[idx+1].value.strng )
            parse_assert( inFunc, NO_SUCH_FUNCTION, 0, inExpr.tokens[idx+1].value.strng )
            select case inFunc->signature
                case "%v.%f(%a,%a)", "%a.%f(%a,%a)"
                    dim as vectorVariable args
                    build_args( 0,3 )
                    call_func
                    return res
                case "%v.%f(%a)", "%a.%f(%a)"
                    dim as vectorVariable args
                    build_args( 0,2 )
                    call_func
                    return res
                case "%v.%f", "%a.%f"
                    dim as vectorVariable args
                    build_args( 0,1 )
                    call_func
                    return res
            end select
        endif
        
    end scope
    #endmacro
       
    select case inExpr.tokens[0].myType
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 
    case token_typ._OPEN_PAREN_                                                 ' 
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''"  
        inExpr = rem_tkn( inExpr, _OPEN_PAREN_ )
        inExpr = rem_tkn( inExpr, _CLOSE_PAREN_ )
        res = Eval( inExpr )
        return res
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' JSB FUNCTIONS  
    case token_typ._FUNCTION_                                                   ' IM FUNCTIONS
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''    
        dim as jsb_function ptr inFunc = context.searchFunc( inExpr.tokens[0].value.toString )
        parse_assert( inFunc, NO_SUCH_FUNCTION, -1, inExpr.tokens[0].value.toString )
        dim as vectorVariable args
        select case inFunc->signature
        case "%f" : call_func
        case "%f %v = %a"
            parse_assert( inExpr.tokens[2].myType = _EQUAL_ASSIGN_, SYNTAX_ERROR, -1,"Expected: = " )
            build_args( 1,2 )
            call_func
        case "%f(%a)"
            build_args(1,1)
            call_func
        case else
            dim as integer nparams = countParameters( inExpr )
            build_args( 0, nparams )
            call_func
        end select
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' User Functions
    case token_typ._RETURN_                                                     ' RETURN
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''"  
        if inExpr.tokens.size = 1 then return 0
        res = Eval( cut_right( inExpr, 1 ) )
        return res
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' User Functions    
    case token_typ._USER_FUNC_                                                  ' Execute
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''    
        dim as jsb_user_func ptr inFunc = context.searchUser( inExpr.tokens[0].value.strng )
        if inFunc = 0 then return DBLQUOTE+ "You func'ed up" +DBLQUOTE
        dim as token_array h = *inFunc->head
        dim as token_array b = *inFunc->body
 
        dim as integer nParams = countParameters( h )
        dim as vectorVariable args
        
        if nParams then 
            build_args(0,nParams)
        endif 
        
        dim as vectorString lbls
       
        for i as integer = 0 to h.tokens.size-1
            if h.tokens[i].myType = _VAR_NAME_ then
                lbls.push_back( h.tokens[i].value.strng )
            endif
        next i
       
        parse_assert( nParams=args.size, ILLEGAL_FUNCTION_CALL, 0, "Parameter count all wrong" )
       
        context.addScope()
        context.setScope( context.curScope+1 )
       
        for i as integer = 0 to nParams-1
            dim as variable tmp
            tmp = args[i]
            tmp.lbl = lbls[i]
            context.variables.add( tmp )
        next i

        res = Parse( b )
       
        context.variables.vars.pop( context.curScope )
        context.setScope( context.curScope-1 )

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Variable Name
    case _VAR_NAME_                                                             '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  
        if inExpr.tokens.size = 1 then
            dim as variable ptr check = context.searchVar( inExpr.tokens[0].value.strng )
            if check then return *check else return inExpr.tokens[0].value
        endif
       
        check_eq()
       
        dim as variable ptr v = context.searchVar( inExpr.tokens[0].value.strng )
        parse_assert( v, VARIABLE_NOT_DECLARED, 0, inExpr.tokens[0].value.strng )
       
        select case v->typ
            case varType._ARRAY_
                handle_array( v )
            case varType._OBJECT_
                handle_object( v )
        end select
       
        if inExpr.tokens.size >= 3 then
            dim as vectorVariable args
            select case inExpr.tokens[1].myType
                case _FUNCTION_
                    dim as jsb_function ptr inFunc = context.searchFunc( inExpr.tokens[1].value.strng )
                    select case inFunc->signature
                        case "%a %f %a", "%a %m %a"
                            build_args(0,2)
                            call_func
                            check_rest( 3 )
                    end select
                case _DOT_
                    select case inExpr.tokens[2].myType
                    case _VAR_NAME_ 'should be handled by object handler
                    case _FUNCTION_
                        dim as jsb_function ptr inFunc = context.searchFunc( inExpr.tokens[2].value.strng )
                            parse_assert( inFunc, NO_SUCH_FUNCTION, 0, inExpr.tokens[2].value.strng )
                            select case inFunc->signature
                                case "%v.%f(%a,%a)", "%a.%f(%a,%a)"
                                    dim as vectorVariable args
                                    build_args( 0,3 )
                                    call_func
                                case "%v.%f(%a)", "%a.%f(%a)"
                                    dim as vectorVariable args
                                    build_args( 0,2 )
                                    call_func
                                case "%v.%f", "%a.%f"
                                    dim as vectorVariable args
                                    build_args( 0,1 )
                            end select
                    end select
                case _MATHOP_
                    if inExpr.tokens[2].myType = _EQUAL_ASSIGN_ then
                        dim as vectorVariable args
                        args.push_back( *v )
                        args.push_back( inExpr.tokens[3].value )
                        res = context.searchFunc( inExpr.tokens[1].value.strng )->func( @context.variables, args )
                        args.clear
                        args.push_back( inExpr.tokens[0].value )
                        args.push_back( res )
                        res = context.searchFunc( "=" )->func( @context.variables, args )
                    else
                        dim as jsb_function ptr inFunc = context.searchFunc( inExpr.tokens[1].value.strng )
                        select case inFunc->signature
                            case "%a %f %a", "%a %m %a"
                                build_args(0,2)
                                call_func
                                check_rest( 3 )
                        end select
                    endif
                case _EQUAL_ASSIGN_
                    dim as vectorVariable args
                    build_args( 0,2 )
                    res = context.searchFunc( "=" )->func( @context.variables, args )
                case else
                    dim as token_array rest = inExpr
                    select case v->typ
                        case varType._NUMBER_
                            rest.tokens[0] = *v
                            res = Eval( rest )
                         case varType._STRING_
                            if inExpr.tokens[1].myType = _OPEN_BRACE_ andalso _
                               inExpr.tokens.back->myType = _CLOSE_BRACE_ then
                                    dim as vectorVariable args
                                    build_args(0,2)
                                    dim as jsb_function ptr inFunc = context.searchFunc( "pluck" )
                                    call_func
                                    return res
                            else
                                rest.tokens[0] = *v
                                res = Eval( rest )
                            endif
                        case varType._BOOL_
                            rest.tokens[0] = *v
                            res = Eval( rest )
                        case else
                            if res.typ = _MALFORMED_ then
                                return *v
                            endif
                    end select
                   
            end select
        endif
       
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''            
    case token_typ._OPEN_BRACE_
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''    
        if inExpr.tokens[1].myType = token_typ._ARRAY_ andalso _
           inExpr.tokens.back->myType = _CLOSE_BRACE_ then
            return inExpr.tokens[1].value
        endif
       
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  
    case token_typ._ARRAY_
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  
        if inExpr.tokens.size = 1 then
            return inExpr.tokens[0].value
        endif
       
        handle_array( @inExpr.tokens[0].value )

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''          
    case token_typ._OBJECT_
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        if inExpr.tokens.size = 1 then
            return inExpr.tokens[0].value
        endif
       
        handle_object( @inExpr.tokens[0].value )
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''      
    case token_typ._NUMBER_
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  
        if inExpr.tokens.size = 1 then
            return inExpr.tokens[0].value
        endif
       
        check_eq()        
       
        if inExpr.tokens[1].myType = _FUNCTION_ then
            dim as jsb_function ptr inFunc = context.searchFunc( inExpr.tokens[1].value.strng )
            select case inFunc->signature
            case "%a %f %a", "%a %m %a"
                call_afa()
                check_rest( 3 )
            end select
        endif
       
        if inExpr.tokens[1].myType = token_typ._MATHOP_ then
            dim as vectorVariable args
            build_args( 0,2 )
            dim as jsb_function ptr f = context.searchFunc( inExpr.tokens[1].value.strng )
            parse_assert( f, -1, -1, "i #%$@ up" )
            res = f->func( @context.variables, args )
            dim as integer idx = inExpr.find( _MATHOP_, 2 )
            if idx <> -1 then
                check_rest(3)
            endif
        endif
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''      
    case token_typ._STRING_
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  
        if inExpr.tokens.size = 1 then
            return inExpr.tokens[0].value
        endif
       
        select case inExpr.tokens[1].myType
        case _MATHOP_
            dim as jsb_function ptr inFunc = context.searchFunc( inExpr.tokens[1].value.strng )
            parse_assert( inFunc, NO_SUCH_FUNCTION, 0, inExpr.tokens[1].value.strng )
            dim as vectorVariable args
            build_args( 0,2 )
            call_func
            if inExpr.tokens[2].myType = _DBL_QUOTE_ then
                check_rest( 5 )
            else
                check_rest( 3 )
            endif
            
        case _DOT_
            select case inExpr.tokens[2].myType
            case token_typ._FUNCTION_, _MATHOP_
                dim as jsb_function ptr inFunc = context.searchFunc( inExpr.tokens[2].value.strng )
                parse_assert( inFunc, NO_SUCH_FUNCTION, 0, inExpr.tokens[2].value.strng )
                select case inFunc->signature
                    case "%a.%f"
                        dim as vectorVariable args
                        build_args( 0,1 )
                        call_func
                    case "%a.%f(%a)"
                        dim as vectorVariable args
                        build_args( 0,2 )
                        call_func
                    case "%a.%f(%a,%a)"
                        dim as vectorVariable args
                        build_args( 0,3 )
                        call_func
                    case else
                        check_eq()
                end select
            end select
        end select
       
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    case token_typ._TRUE_, token_typ._FALSE_
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  
        if inExpr.tokens.size = 1 then
            return inExpr.tokens[0].value
        endif
       
        dim as token ptr t = inExpr.findPtr( _BITOP_ )
        
        if t then
        
            dim as integer nargs = 0
            for i as integer = 0 to inExpr.tokens.size-1
                if inExpr.tokens[i].myType = _BITOP_ then
                    nargs+=1
                endif
            next i
            
            nargs+=1
 
            dim as vectorVariable args
            build_args(0,nargs)
            dim as jsb_function ptr inFunc = context.searchFunc( t->value.strng )
            call_func
            
        endif
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    case token_typ._END_LINE_
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  
        return res
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  
    case else
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  
        if inExpr.tokens[0].myType <> _OUT_ then
            parse_assert( 0, SYNTAX_ERROR, -1, "Malformed Expression: " + inExpr.tokens[0].tostring )
        endif
    end select
   
    return res
end function

function Parse( byref inScript as token_array ) as variable
    dim as variable res = "true"
   
    if inScript.tokens.size = 0 then return "false"
   
    #macro rebuild_line(tknarray1,tknarray2)
    select case res.typ
        case varType._NUMBER_, varType._STRING_, varType._BOOL_, varType._ARRAY_, varType._OBJECT_
            dim as integer idx = tknarray2.find( tknarray1 )
            for aa as integer = idx to idx+tknarray1.tokens.size-1
                tknarray2.tokens.pop( idx )
            next aa
            if idx > tknarray2.tokens.size-1 then
                tknarray2.tokens.push_back( res )
            else
                tknarray2.tokens.insert(idx,res)
            endif
    end select
    #endmacro
   
    #macro check_id( tkn )
    Scope
        dim as integer id = curLine.find( tkn )
        if id > 0 then
            dim as token_array rhs = get_rhs( curLine, tkn )
            if rhs.tokens.size > 2 then
                res = Parse( rhs )
                check_error()
                curLine = cut_left( curLine, id )
                curLine.tokens.push_back( res )
            endif
        endif
    end Scope
    #endmacro
   
    #macro check_ids()
        check_id( _EQUAL_ASSIGN_ )
        check_id( _EQUAL_COMPARE_ )
        check_id( _GREATER_THAN_ )
        check_id( _LESS_THAN_ )
        check_id( _EQUAL_OR_GREATER_ )
        check_id( _EQUAL_OR_LESS_ )
        check_id( _NOT_EQUAL_ )
    #endmacro
   
    #macro move_along()
        Continue for
    #endmacro
   
    #macro check_for_vars( n, _var )
        select case curLine.tokens[n].myType
        case token_typ._NUMBER_ : _var = curLine.tokens[n].value.number
        case token_typ._VAR_NAME_
            if n+2 < curLine.tokens.size-1 then
                if curLine.tokens[n+1].myType = _DOT_ then
                    dim as integer i = n
                    dim as token_array for_check
                    Do
                        if curLine.tokens[i].myType = _TO_ then exit do
                        if curLine.tokens[i].myType = _STEP_ then exit do
                        if curLine.tokens[i].myType = _OPEN_CBRACE_ then exit do
                        for_check.tokens.push_back( curLine.tokens[i] )
                        i+=1
                        if i > curLine.tokens.size-1 then exit do
                    loop
                    if for_check.tokens.size > 0 then
                        _var = Eval( for_check ).number
                    endif
                else
                    dim as variable ptr check3 = context.searchVar( curLine.tokens[n].value.strng )
                    if check3 andalso check3->typ = varType._NUMBER_ then _var = check3->number
                endif
            else
                dim as variable ptr check3 = context.searchVar( curLine.tokens[n].value.strng )
                if check3 andalso check3->typ = varType._NUMBER_ then _var = check3->number
            endif
        case token_typ._FUNCTION_
            dim as token_array for_check
            Do 
                if curLine.tokens[i].myType = _TO_ then exit do
                if curLine.tokens[i].myType = _STEP_ then exit do
                if curLine.tokens[i].myType = _OPEN_CBRACE_ then exit do
                for_check.tokens.push_back( curLine.tokens[i] )
                i+=1
                if i > curLine.tokens.size-1 then exit do
            loop
            _var = Eval( for_check ).number
        end select
    #endmacro
   
    #macro process_if()
        if curLine.tokens[0].myType = _IF_ then
            context.addScope()
            context.setScope( context.curScope+1 )
            dim as token_array cif = cut_right( curLine, 1 )
            dim as integer r = cif.find( _OPEN_CBRACE_ )
            cif = cut_left( cif, r-1 )
            dim as integer bitop = cif.find( _BITOP_ )
            if bitop = -1 then
                paren_pop( cif )
                dim as variable check = Parse( cif )
                if check.bool = JSON_BOOL._TRUE_ then
                    dim as integer bgn = curLine.find( _OPEN_CBRACE_ )
                    dim as token_array ex
                    getConditionalExpr( ex )
                    res = Parse( ex )
                    check_error()
                elseif curLine.find(_ELSE_) <> -1 then
                    dim as integer bgn = curLine.find( _ELSE_ )+1
                    dim as token_array ex
                    getConditionalExpr( ex )
                    res = Parse( ex )
                    check_error()
                endif
            else
                dim as integer nExpr = countParens( cif )
                for j as integer = nExpr to 1 step -1
                    dim as token_array chk = getParenExpr( cif, j )
                    res = Eval( chk )
                    check_error()
                    rebuild_line( chk,cif )
                next j
                dim as variable check = Eval( cif )
                if check.bool = JSON_BOOL._TRUE_ then
                    dim as integer bgn = curLine.find( _OPEN_CBRACE_ )
                    dim as token_array ex
                    getConditionalExpr( ex )
                    res = Parse( ex )
                    check_error()
                elseif curLine.find(_ELSE_) <> -1 then
                    dim as integer bgn = curLine.find( _ELSE_ )+1
                    dim as token_array ex
                    getConditionalExpr( ex )
                    res = Parse( ex )
                    check_error()
                endif
            endif
            context.variables.vars.pop( context.curScope )
            context.setScope( context.curScope-1 )
            move_along()
        endif
    #endmacro
   
    #macro process_while()
        if curLine.tokens[0].myType = token_typ._WHILE_ then
            context.addScope()
            context.setScope( context.curScope+1 )
            dim as integer bgn = curLine.find( _OPEN_CBRACE_ )
            dim as token_array tmp = cut_idx( curLine, 1, bgn-1 )
            dim as integer nExpr = countParens( tmp )
            for j as integer = nExpr to 1 step -1
                dim as token_array curExpr = getParenExpr( curLine, j )
                dim as variable check = Eval( CurExpr )
                if check.bool = JSON_BOOL._TRUE_ then
                    if bgn <> -1 then
                        dim as token_array ex
                        getConditionalExpr(ex)
                        res = Parse( ex )
                        check_error()
                        res = Parse( curLine )
                        check_error()
                    else
                        exit for
                    endif
                else
                    exit for
                endif                
            next j
            context.variables.vars.pop( context.curScope )
            context.setScope( context.curScope-1 )
            move_along()
        endif
    #endmacro
   
    #macro process_for()
        if curLine.tokens[0].myType = token_typ._FOR_ then
            parse_assert( curLine.tokens[1].myType = token_typ._VAR_NAME_, i, ILLEGAL_FUNCTION_CALL, "Expected: variable" )
            parse_assert( curLine.tokens[2].myType = token_typ._EQUAL_ASSIGN_, i, ILLEGAL_FUNCTION_CALL, "Expected: =" )
            dim as double _bgn, _end
            check_for_vars( 3, _bgn )
            check_for_vars( 5, _end )
            dim as integer stepidx = curLine.find( _STEP_ )
            dim as integer _step
            if stepidx <> -1 then
                check_for_vars( stepidx+1, _step )
            else
                _step = 1
            endif
            dim as integer bgn = curLine.find( _OPEN_CBRACE_ )
            dim as token_array ex
            getConditionalExpr(ex)
            dim as variable ptr v = context.searchVar( curLine.tokens[1].value.strng )
            if v = 0 then
                dim as variable f = 0
                context.addScope()
                context.setScope( context.curScope+1 )
                f.lbl = curLine.tokens[1].value.strng
                context.variables.add( f )
                v = context.searchVar( f.lbl )
            endif
            for j as integer = _bgn to _end step _step
                v->number = j
                Parse( ex )
                check_error()
            next j
            context.variables.vars.pop( context.curScope )
            context.setScope( context.curScope-1 )
            move_along()
        endif
    #endmacro
   
    #macro getConditionalExpr(tknarray)
        if curLine.tokens[ bgn ].myType = _OPEN_CBRACE_ then
            dim as integer llevel = 1
            dim as integer rlevel = 0
            Do while llevel <> rlevel
                bgn+=1
                if curLine.tokens[ bgn ].myType = _OPEN_CBRACE_ then llevel += 1
                if curLine.tokens[ bgn ].myType = _CLOSE_CBRACE_ then rlevel += 1
                if bgn > curLine.tokens.size-1 then exit do
                if llevel = rlevel then exit do
                tknarray.tokens.push_back( curLine.tokens[ bgn ] )
            loop
        else
            parse_assert( 0, SYNTAX_ERROR, i, "Expected Open Brace" )
        endif
    #endmacro
   
    #macro process_select()
        if curLine.tokens[0].myType = _SELECT_ then
            dim as token_array varArr = getParenExpr( curLine, 1 )
            dim as variable var_select = Eval( varArr )
            dim as integer caseIdx = curLine.find( _CASE_ )
            Do while caseIdx <> -1
                dim as variable chk = curLine.tokens[ caseIdx+1 ].value
                if chk = var_select then
                    context.addScope()
                    context.setScope( context.curScope+1 )
                    dim as integer bgn = caseIdx+2
                    dim as token_array ex
                    getConditionalExpr( ex )
                    res = Parse( ex )
                    check_error()
                    context.variables.vars.pop( context.curScope )
                    context.setScope( context.curScope-1 )
                    exit do
                endif
                caseIdx = curLine.find( _CASE_, caseIdx+1 )
            loop
            move_along()
        endif
    #endmacro
   
    #macro check_arrays()
        dim as integer nBr = countBraces( curLine )
        if nBr > 0 then
            for j as integer = nBr to 1 step -1
                dim as token_array curBrace = getBraceExpr( curLine, j )
                if curBrace.tokens.size > 1 then
                    res = Eval( curBrace )
                    check_error()
                    rebuild_line( curBrace,curLine )
                endif
            next j
        endif
    #endmacro
   
    #macro check_curlies()
        if curLine.tokens[0].myType = _OPEN_CBRACE_ then
            context.addScope()
            context.setScope( context.curScope+1 )
            dim as integer bgn = 0
            dim as token_array ex
            getConditionalExpr( ex )
            res = Parse( ex )
            check_error()
            context.variables.vars.pop( context.curScope )
            context.setScope( context.curScope-1 )
            move_along()
        endif
    #endmacro
   
    #macro check_eval()
        if curLine.tokens[0].myType = _EVAL_ then
            dim as integer idx = -1
            if curLine.tokens[1].myType = _OPEN_PAREN_ then
                idx = 2
            else
                idx = 1
            endif
           
            dim as variable ptr v = context.searchVar( curLine.tokens[idx].value.strng )
            dim as string s = ""
       
            if v then s = v->strng else s = curLine.tokens[idx].value.strng
            dim as token_array expr
            expr.init( s )
            res = Eval( expr )           
            check_error()
            move_along()
        endif
    #endmacro
   
    #macro check_parse()
        if curLine.tokens[0].myType = _PARSE_ then
            dim as integer idx = -1
            if curLine.tokens[1].myType = _OPEN_PAREN_ then
                idx = 2
            else
                idx = 1
            endif
           
            dim as variable ptr v = context.searchVar( curLine.tokens[idx].value.strng )
            dim as string s = ""
           
            if v then s = v->strng else s = curLine.tokens[idx].value.strng
            dim as token_array newScript
            newScript.init( s )
            res = Parse( newScript )
            check_error()
            move_along()
        endif
    #endmacro
    
    #macro check_out()
        if curLine.tokens.size > 1 then
            if curLine.tokens[0].myType = _OUT_ then
                dim as integer idx = -1
                if curLine.tokens[1].myType = _OPEN_PAREN_ then
                    idx = 2
                else
                    idx = 1
                endif
                
                dim as variable ptr v = context.searchVar( curLine.tokens[idx].value.strng )
                dim as string s = ""
                
                if v then s = v->strng else s = curLine.tokens[idx].value.strng 
                
                context.out_string = s 
                move_along()
            endif
        endif
    #endmacro
    
    #macro func_swap( tknarray )
        if tknarray.tokens.size >= 3 andalso tknarray.find( _MATHOP_ ) <> -1 then
            dim as integer idx = tknarray.find( _FUNCTION_ )
            
            if idx = -1 then tknarray.find( _USER_FUNC_ )
            
            if idx <> -1 then
                if idx > 1 then
                    if tknarray.tokens[ idx-1 ].myType = _DOT_ then idx -= 2
                end if
                dim as integer aa = idx
                dim as token_array fExpr
                Do
                    if tknarray.tokens[aa].myType = _MATHOP_ then exit do
                    if tknarray.tokens[aa].myType = _END_LINE_ then exit do
                    fExpr.tokens.push_back( tknarray.tokens[aa] )
                    aa += 1
                    if aa = tknarray.tokens.size then exit do
                loop

                res = Eval( fExpr )
                check_error()
                rebuild_line( fExpr, tknarray )
                rebuild_line( fExpr, curLine )

                if tknarray.find( _FUNCTION_ ) <> -1 orelse tknarray.find( _USER_FUNC_ ) <> -1 then
                    res = Parse( tknarray )
                    rebuild_line( tknarray, curLine )
                    check_error()
                    move_along()
                else
                    res = Eval( tknarray )
                    check_error()
                    'move_along()
                endif
            endif
        endif
    #endmacro
    
    #macro paren_pop( tknarray )
        if tknarray.tokens[0].myType = _OPEN_PAREN_ then 
            tknarray.tokens.pop( 0 )
            if tknarray.tokens[ tknarray.tokens.size-1 ].myType = _CLOSE_PAREN_ then tknarray.tokens.pop( tknarray.tokens.size-1 )
        endif
    #endmacro
    
    #macro check_error()
        if res.typ = _NULL_ orelse res.typ = _MALFORMED_ then
            parse_assert( 0, -1, i, curLine.tostring )
            return res
        endif        
    #endmacro
    
    dim as integer nLines = lineCount( inScript )
    
    
    for i as integer = 1 to nLines
       
        dim as token_array curLine = getLine( i, inScript )    
              
            check_curlies() 
            check_arrays()
            process_for() 
            process_while()
            process_if()
            process_select()
            check_eval()
            check_parse()
            check_ids() 
            check_out()
       
        dim as integer nExpr = countParens( curLine )
       
        if nExpr then
            for j as integer = nExpr to 0 step -1
                
                dim as token_array curExpr = getParenExpr( curLine, j )
                dim as integer nParams = countParameters( curExpr )
                func_swap( curExpr )
                
                    if nParams andalso j = nExpr then
                        for k as integer = 1 to nParams
                            dim as token_array curParam = getParam( curExpr, k )
                            if curParam.tokens.size > 1 then
                                res = Eval( curParam )
                                rebuild_line( curParam,curLine )                        
                            endif
                        next k
                    else
                        res = Eval( curExpr )
                        rebuild_line( curExpr,curLine )
                    endif
                    
            next j
        else
            dim as token_array curExpr = getParenExpr( curLine, 0 )
            func_swap( curExpr )
            res = Eval( curExpr )      
            check_error()
        endif
       
    next i

    return res
end function

function Execute( byval inScript as string ) as variable
    dim as variable res
    context.initScript( inScript )
    dim as double tnow
    tnow = timer 
    res = Parse( context.script )
    ? timer-tnow
    return res
end function

'screen 19
randomize
dim as string s = LoadFileAsString("work2.jsb")
'
''context.initScript( s )
Execute( s )
'
sleep
Last edited by rolliebollocks on Jul 13, 2014 16:06, edited 24 times in total.
rolliebollocks
Posts: 2655
Joined: Aug 28, 2008 10:54
Location: new york

Re: json basic scripting language

Post by rolliebollocks »

EXAMPLES

Array Demo 1

Push, Pop, Push_Back, Length, First, Last

Code: Select all

var array = [1,2,3,4,5];
array.push( 1, 12 ); 

for i = 0 to array.length-1
{
	print( array[i] );
}; 

array.pop( 0 );
print( array[0] );

array.push_back( "twelve" );
array.push( 0, "fifty" );
print( array.first );
print( array.last );
Array Demo 2: Dereferencing nested array with assign

Code: Select all

var arr = [0,[1,2],10,20,30];
arr[1][0] = 12+12;

print( arr[1][0] );
Pass array to user defined function (1)

Code: Select all

function arr_print( arr ) {
	var s = "";
	s += "[";
	
	for i = 0 to arr.length-1 {
		s += arr[i];
		if ( i != arr.length-1 ) {
			s += ",";
		};
	};
	
	s += "]";
	
	return s;
};

var arr = [1,2,3,4,5];

print( arr_print( arr ) );
A nice feature of JSB is that left/right/mid/slice are overloaded for both strings and arrays. Here, JSB is dereferencing a nested array and handling an ambiguous call correctly. (wow).

Code: Select all

var arr = [["one","two"],["three","four"]];
arr[0].push_back( "millions" );

print( arr[0][2].left( 3 ) );
print( arr[0][2].right( 3 ) );
print( arr[0][2].mid( 3, 3 ) );
print( arr[0][2].slice( 3, 6 ) );
When I was coding this feature, I had to make sure it worked with math operators properly. Here is proof that it does. (wow).

Code: Select all

var arr = [["one","two"],["three","four"]];
arr[0].push_back( "millions" );

var s = arr[0][0] + arr[0][1] + arr[0][2];
print( s );
Here it is working with += (wow)

Code: Select all

var arr = [["one","two"],["three","four"]];
arr[0].push_back( "millions" );

var s = arr[0][0];
s += arr[1][0];
print( s );
This example takes an array as an argument and then prints out the contents in a form that you can use the internal "eval" function to evaluate. (that's great).

Code: Select all

function print_array( arr ) {
	var s = "";
	s += "[";
	
	for i = 0 to arr.length-1 {
		if (i == arr.length - 1) { 
			s += arr[i];
		} else {
			s += arr[i] + ",";
		};
	};
	
	s += "]";
	print( s );

	return s;
};

var array = [1,2,3,4,5];

print_array( array );
This is an example of how you can embed functions into index brackets. (yeah)

Code: Select all

var arr = [10,20,30,40,50];
var idx = rnd*arr.length;
print( arr[ fix(idx) ] );
This is a user defined function which chooses at random an element of an array.

Code: Select all

function choose( arr ) {
	var idx = fix( rnd*arr.length );
	return arr[ idx ];
};

var arr = ["one","two","three","four","five"];

for i = 0 to 5 {
	print( choose( arr ) );
};
Here is an example of an array index being used to dereference an array index. (this is less impressive than it sounds).

Code: Select all

var arr1 = [0,1,2,3,4];
var arr2 = [10,20,30,40,50];

print( arr2[ arr1[1] ] );
for loop demo:

Code: Select all

var myArray = [10,20,30,40,50,60];
var l = myArray.length - 1;

for x = 0 to l
{
	print( myArray[x] );
};
very basic user defined function

Code: Select all

function myfunc( x, y, z ) {
	return x+y+z;
};

myfunc( 1,2,10 );
print( myfunc( 1,2,10 ) );
if/else with bitwise and

Code: Select all

var x = 10;

if ( x < 15 ) && ( x < 25 ) { 
	print(x);
	} else {
	print("X is not greater than 15");
};
demos very basic object construction with key dereferencing and assignment

Code: Select all

var myObject =
{
	"mykey": "somevalue"
};

myObject["mykey"] = "super nun";
myObject.mykey = "fungus";

print( myObject["mykey"] );
print( myObject.size );
print( myObject.mykey );
two objects being stored in array

Code: Select all

var obj = {
	"txt": "word",
	"def": "something like this"
};

var obj2 = obj;

print( obj2.def );

var arr = [];

arr.push_back( obj );
arr.push_back( obj2 );

print( arr[0]["txt"] );

var s = "def";

print( arr[1][ s ] );
print( arr[1].s );
same as last one except assignment added

Code: Select all

var obj1 = {
   "this": "this",
   "that": "that"
};

var obj2 = {
	"this": "this2",
	"that": "that2"
};

var arr = [];

arr.push_back( obj1 );
arr.push_back( obj2 );

print( arr[0].this );
print( arr[1].that );
print( arr[0]["this"] );

arr[0].this = "THIS!" + "THAT?";
print( arr[0].this );
object construction via function

Code: Select all

function newWordObject() {
	var res = {
		"txt": "",
		"tag_tkns": [],
		"phone_tag": "()",
		"accent": 0,
		"tags": []
	};
	return res;
};

var word1 = newWordObject();

print( word1.phone_tag );

rnd_range via user func

Code: Select all

function rnd_range( lo, hi ) {
	var res = int( rnd*(hi - lo + 1)+lo );
	return res;
};

var x = rnd_range( 10,20 );
print( x );

scope demo

Code: Select all

var x = 10;

{
	print( x );
	var y = 20;
	print( y );
};

print( x );
print( y );
select/case demo

Code: Select all

var x = 3;

select (x)
{
	case 1 { print(1); }
	case 2 { print(2); }
	case 3 { print(3); }

};

internal split function splits a string in an array over multiple delimiters

Code: Select all

var arr = [];
"This is a test. Check out my awesome test.".split( " .", arr );

for i = 0 to arr.length-1
{
	print( arr[i] );
};

You can call most functions with either JavaScript like or BASIC-like notation:

Code: Select all

var string = "This is a test. Check out my awesome test.";
var arr = [];
split( string, " .", arr );
print( arr.length );

for i = 0 to arr.length-1
{
	print( arr[i] );
};

var s = "Hello " + "world";
print( s );

print( s.slice( 4,9 ) );
print( slice( s, 4, 9 ) );
Demos some basic string functions

Code: Select all

var s = "Hello World";

var s2 = s.right(5) + s.left(5) + "!!!!!!" + s.slice(3,6) + s.mid(3,3);

print(s2);
Escape sequences are no supported

Code: Select all

var s = "\"Hello World\"";
print( s );

s = "Hello \n World";

print( s );
 
while loop

Code: Select all

var x = 10;
var y = 0;

while ( y < x )
{
	y += 1;
	print(y);
};

Last edited by rolliebollocks on Jul 14, 2014 18:15, edited 8 times in total.
rolliebollocks
Posts: 2655
Joined: Aug 28, 2008 10:54
Location: new york

Re: json basic scripting language

Post by rolliebollocks »

I'm closing in on the end of this one. I have to add variable scoping, some control flow functions, bitwise operators (which are proving the toughest of the bunch) and self-executing functions. The sourceforge download has been updated and so have the pastes to the board. New examples are included. Many string/array functions can be called using BASIC-like or JS style syntax ie:

Code: Select all

"I made a doodie".length = len("I made a doodie")
Then, when everything is added, I will go through and optimize. I may add user defined object methods beforehand.

Adding new base functions is easy.

#1. Go into jsb_lexer.bas

find this:

Code: Select all

function is_jsb_func( byval s as string ) as integer
    dim as string all_func_names = ",var,function,print,sqr,+,/,*,^,%," _
                                 + "sin,cos,tan,asin,acos,atan,atan2,sqr,abs," _
                                 + "log,fix,int,frac,sgn,rnd,mod," _
                                 + "len,asc,chr,left,right,mid,lcase,ucase,instr," _
                                 + "pluck,load_file_as_string,&,beep," _
                                 + "length,pop,push,sleep,push_back,last,first," _
                                 + "size,split,slice,MYNEWFUNCTION,"
    dim as string this_func = ","+s+","
    return instr( all_func_names, this_func )
end function
add your new function to the end of it (enclosed in commas)

#2. go into jsb_functions.bas and add something like

Code: Select all

function _MYNEWFUNC( byval varMap as jsb_var_map ptr, byref args as vectorVariable ) as variable
      dim as integer length = args.size
      for i as integer = 0 to args.size-1
           print( args[i].tostring )
      next i

      return "true"
end function
#3. then you must bind the function to the context so go into jsb_context.bas and find

Code: Select all

sub InitializeFunctions( byref context as jsb_context )
At the bottom add..

context.jsb_functions.add( "MYNEWFUNC", @_MYNEWFUNC, "%f(%a,%a,%a)" )

This is a function which will take 3 arguments.. For now there are no varlen argument functions, but I think that would easy enough to add (sometime later).

#4. Enjoy your new function and check out other functions for added functionality.
rolliebollocks
Posts: 2655
Joined: Aug 28, 2008 10:54
Location: new york

Re: json basic scripting language

Post by rolliebollocks »

Okay, I fixed the nesting glitch, added scopes, select case, and bitwise ops. I will add dynamic scoping via {} and maybe object methods, but the scripting language does more or less what I need it to do. There may be more bugs I don't know, and I won't know until I've time to actually use the language, which will replace the old scripting language in Infinite Monkeys. At any rate this was a fun project to work on, and it seems to be mostly functioning, properly. So, yay.
rolliebollocks
Posts: 2655
Joined: Aug 28, 2008 10:54
Location: new york

Re: json basic scripting language

Post by rolliebollocks »

I fixed a bunch of bugs last night, mostly surrounding this:

arr[x] += number

There was a problem with select/case executing code twice, which was a one line fix too. Other than those the code appears clean.
Post Reply