Discussion Druggy Code O_o

Nestharus

o-o
Reaction score
84
So I was just looking at notes from a language I was working on and I came across this.

JASS:
function ReturnThis takes nothing
    out static export //no name needed
       integer i = out n
    end
end

scope
   function Woah takesnothing
       integer n =4
     
       while(n++<10) do
            ReturnThis()
            Print(i)           //5
                               //6
                               //7
                               //8
                               //9
                               //10
        end
    end
end


the export keyword exports a symbol or group of symbols from one scope to another scope. In the above example, the symbol "i" is being exported. the "static" means that it's not instanced (like the field of an instance of a class). the "out" keyword means go out to the scope that is using this.

So all in all, the result is that anything that calls ReturnThis will get a symbol of type integer i that is set to a variable n. n has the "out" modifier, meaning that it is located in the calling scope.

function Woah has an integer n and a while loop. Inside of this loop, it continues to call ReturnThis and then prints i, which was exported from ReturnThis. The result is 5, 6, 7, 8, 9, 10 being printed out to the screen.

Here are the notes
JASS:
/*
*   Comment
*
*   Comments may be either single line or delimited
*/

   //a single line comment
  
   /*
        a multi-line comment
    */
  
/*
*   multi-line comments may be nested
*/

   /* /* hi */*/
  
/*
*   Statement
*
*   Every single line statement must end with either a new line or EOF.
*
*   A single line statement may be continued to another line with \.
*
*   Delimited statements include
*
*       1.  ( )
*       2.  " "
*       3.  ' '
*       4.  { }
*/
  
/*
*   Scope
*
*   There are five different types of named scopes
*
*       1.  function scope
*       2.  property scope
*       3.  operator scope
*       4.  type scope
*       5.  scope
*
*   Of these five types, they are split into the following name spaces
*
*       1.  function scope          A
*       2.  property scope          B
*       3.  operator scope          C
*       4.  type scope              D
*       5.  scope                   D
*
*   The reason why type scopes and scopes share the same space is because
*   they both utilize the lookup operator (.)
*
*/

   set hi.v=5

/*
*   When a scope is used, the code inside of it is simply placed into the space of
*   that scope. There is no scope declaration, there is only scope setting. This
*   means that if two scopes are the same, the code inside of them share the same space.
*   However, there can still be differences between the two scopes (more later).
*/

/*
*   The scope may be anonymous or named
*/

   scope label
    end
  
   scope
    end
  
/*
*   Any scope of any type may be nested into any other scope of any type
*/

   scope
       scope rawr
           scope foo
            end
        end
    end

/*
*   Function Scope
*
*   A function scope is a scope with a limited lifetime. There are two special scopes
*   under the function scope.
*
*       1.  property scope
*       2.  operator scope
*
*   However, the three scopes do not share the same name space.
*
*   A function scope is accessed in the following manner
*
*/

   function label takes arguments returnstype
    end

/*
*   An example of a function
*/

   function Hello takesnothingreturnsnothing
    end
  
/*
*   Functions may have either an explicit or implicit return type
*/

   function Hello takesnothing
    end
          
/*
*   The scope signature does not include the return type
*
*   If the same scope is accessed in two incompatible ways, the
*   scope can't be created. As such, a syntax error will occur.
*/

   function Hello takesnothingreturnsstring
       return"hi"
    end
      
   function Hello takesnothingreturnsinteger
       return5
    end
      
/*
*   Note that an explicit return type will only accept that return type.
*
*   Implicit return types may work with explicit return types so long
*   as the implicit return types are compatible with the explicit return types.
*/

   //both of these return agents, so the scope is still valid
   function Boo takesnothingreturnsagent
       returnCreateUnit(Player(0),'hfoo',0,0,270)
    end
      
   function Boo takesnothing
       returnCreateItem('afac',0,0)
    end
          
/*
*   The function scope is used with the call keyword.
*
*   The parameters are passed in between the ( ).
*/

   call Boo()
          
/*
*   Please keep in mind JASS syntax for arguments.
*/

/*
*   Implicit return types return the compatible type among
*   types that the function returns.
*/

   function ReturnsWidget takesinteger o
       if(o ==5)then
           returnCreateUnit(Player(0),'hfoo',0,0,270)
        end
      
       returnCreateItem('afac',0,0)
    end

/*
*   Unreachable statements are removed from functions
*/

   function ReturnsItem takesnothing
       if(false)then
           returnCreateUnit(Player(0),'hfoo',0,0,270)
        end
      
       returnCreateItem('afac',0,0)
    end
      
/*
*   Property Scope
*
*   The property scope is a function scope that acts like a variable
*
*   It has two forms
*/

   //getter, must return something
    property label
    end
  
   //setter
    property label =integer o
    end
      
/*
*   Example of properties
*/

    internal privateinteger m =0
  
    property i
       return m
    end
  
    property i =integer o
       set m = o
    end
  
   set i =4//accessed just like a variable
   integer t = i
      
/*
*   The operator scope is a function that uses operator syntax
*
*   Keep in mind that any type can be used in the operators.
*   integer isn't being used for any particular reason.
*/

   //all operators
   //
   //static or non-static
   //
   //must return something
   operator+integer i
       return(thistype)((integer)this+ i)
    end
   operator-integer i
       return(thistype)((integer)this- i)
    end
   operator/integer i
       return(thistype)((integer)this/ i)
    end
   operator*integer i
       return(thistype)((integer)this* i)
    end
   operator & integer i
       return//?
    end
   operator | integer i
       return//?
    end
   operator ^ integer i
       return//?
    end
   operator ~
       return//?
    end
   operator<<integer i
       return//?
    end
   operator>>integer i
       return//?
    end
   operator>>>integer i
       return//?
    end
  
   //static or non-static
   //
   //must return something
   operator<integer i
       return(integer)this< i
    end
   operator<=integer i
       return(integer)this<= i
    end
   operator>integer i
       return(integer)this> i
    end
   operator>=integer i
       return(integer)this>= i
    end
   operator==integer i
       return(integer)this== i
    end
   operator !=integer i
       return(integer)this != i
    end
  
   //all operators
   //
   //static or non-static
   //
   //must return something
    reference operator=thistype i
       setthis= i
       returnthis
    end
    reference operator+=integer i
       setthis=(thistype)((integer)this+ i)
       returnthis
    end
    reference operator-=integer i
       setthis=(thistype)((integer)this- i)
       returnthis
    end
    reference operator*=integer i
       setthis=(thistype)((integer)this* i)
       returnthis
    end
    reference operator/=integer i
       setthis=(thistype)((integer)this/ i)
       returnthis
    end
    reference operator &=integer i
       //code
    end
    reference operator |=integer i
       //code
    end
    reference operator ^=integer i
       //code
    end
    reference operator>>=integer i
       return(thistype)((integer)this/R2I(Pow(2, i)+.5))
    end
    reference operatorthistype reference this<<=integer i
       return(thistype)((integer)this*R2I(Pow(2, i)+.5))
    end
    reference operator>>>=integer i
       //code
    end

   //static or non-static
   //
   //typecast must be of a valid type
   //
   //  operator (integer)
   //  operator (real)
   //
   //a typecast operator is required for any type that isn't either
   //imported or extended
   //
   //any type may typecast to any other type that it extends without an operator
   //only non-virtual types may typecast to types that extend it
   //
   //must return the type
   //
   operator(string)
       return"foo"
    end

   //static or non-static
   //
   //must return something
    reference operatorthis++
       setthis=(thistype)((integer)this+ i)
       return(thistype)((integer)this-1)
    end
    reference operator++this
       setthis=(thistype)((integer)this+ i)
       returnthis
    end
    reference operator this--
       setthis=(thistype)((integer)this- i)
       return(thistype)((integer)this+1)
    end
    reference operator--this
       setthis=(thistype)((integer)this- i)
       returnthis
    end

   //static or non-static
   //
   //any valid expression
   //
   //similar to properties
   //
   //  operator [integer i]
   //  operator [integer i, integer i2]
   //  operator [integer i][integer i2]
   //  operator [integer i, integer i2][integer i3]
   //  operator [integer i] = integer v
   //  operator [integer i, integer i2, integer i3][integer i4][integer i5] = integer v

   //static or non-static
   //
   //must return something
   operatorandinteger i
       if((integer)this==0or(integer)i ==0)then
           returnfalse
        end

       returntrue
    end
   operatororinteger i
       if((integer)this !=0or(integer)i !=0)then
           returntrue
        end

       returnfalse
    end
   operatornot
       if((integer)this==0)then
           returnfalse
        end

       returntrue
    end
  
   //static or non-static
   //
   //must return something
   operator ?
       if((integer)this==0)then
           returnfalse
        end
      
       returntrue
    end
  
   //

   //can take whatever and be overloaded like a regular function
   //if this doesn't use override, it's automatically allocated and so on
   //if it does, it isn't
   operator new takesnothing
      
    end
  
    override operator new takesinteger i
       setthis= allocate()

       returnthis
    end

   //if any form of new is created, the default empty new is lost
  
   operator delete
    end

   //alternative
   //override operator delete
   //  call deallocate()
   //end

/*
*   Type Scope
*
*   The type scope creates a new variable type.
*
*   The primitive/native type it extends from dictates what variable type
*   it will work with.
*/

   type test extendsinteger
   //integer this
  
   type test2 extendsunit
   //unit this
  
   type test3 extendswidget
   //widget this
      
/*
*   It may have statements (either one or many)
*/

   type test2 extendsintegerscope
    end
  
   type test2 extendsintegerinteger oh  //one-liner with member oh
      
/*
*   The label of a type may not share the same name as the label of a scope
*
*   This is because both of them use the same lookup operator
*/
      
   scopeinteger//error
    end
  
/*
*   Access Modifier
*
*   public
*       can be seen from anywhere
*
*   protected
*       can be seen by extending types
*
*   private
*       can be seen only within the direct scope
*
*   internal
*       can be seen within the file or trigger
*       may be applied to other access modifiers
*
*   friend
*       can be seen only within scope (all scopes merging with it too)
*/

   publicinteger i
   protectedinteger i
   privateinteger i
    internal integer i
  
    internal publicinteger i
    internal protectedinteger i
    internal privateinteger i
  
   type a extendsprivateinteger   //integer access stops at a
                                       //can be interpreted as integer.
                                      
   type a extendsprotectedinteger   //integer access for children of a
                                       //can only be interpreted as integer by children
  
   type b extendsprivate a          //can see integer, but child can't
                                       //can't be interpreted as a
  
   type a extends internal integer   //integer access only to other code in same file/trigger.
                                       //can only be interpreted as integer by other code in same file/trigger.
                                      
   type a extendsinteger             //anything can see integer from a
                                       //anything can interpret a as integer
                                      
   scope
       privatescope
           integer i
        end
       set i =5//good
    end
   set i =4//bad
  
    friend integer i
  
   scope a
    end
  
   scope d
    end
  
   scope e
    end
  
   scope b
       //can only be seen by members of a if those
       //members decide to merge with b
       //nothing else can see it
        friend a integer i
      
       //can be seen by a,d,e when merged
        friend a,d,e integer i
      
       //can be seen by a,d,e
       public friend a,d,e integer i
      
       //friends are useful for things like with what modules used to do
       //you may only want the variable to be seen by a certain module
       //JASS has no modules, but it has constructs that can be used
       //to similar effect
    end
  
/*
*   Variable
*
*   A variable may be either implicit, global, or local.
*
*   A global variable is a variable that exists outside of a function scope.
*   A local variable is a variable that exists inside of a function scope.
*   An implicit variable exists either globally or locally depending on where it is used.
*/

    global integer i       //explicitly global variable
   localinteger i        //explicitly local variable
   integer i              //may be global or local
  
   //explicit globals block
   globals
       integer i
    end
  
   //explicit locals block
    locals
       integer i
    end
  
/*
*   An example of implicit variables
*/

   integer i //i is local to Foo
  
   function Foo takesnothing
       set i =4
    end
  
   integer m //m is local to the anonymous function in this scope
  
   set m =5
  
   integer o //o is global
  
   set o =3
  
   function Foo takesnothing
       set o =4
    end
  
   localinteger p
  
   function Foo takesnothing
       set p =4//syntax error
    end
  
   localinteger z
    global integer z //no syntax error
  
   localinteger L
   integer L //global, no syntax error
  
   function Foo takesnothing
       set L =5
    end
   function Foo takesinteger i
       set L =5
    end
  
/*
*   Variable types may also be implicit
*/

    var i
  
   set i =4//integer
  
    var o
  
   set o =CreateUnit(...)
   set o =CreateItem(...)//widget
  
/*
*   Intelligent Simplification
*
*   Code is reordered based on use
*   If there is cyclical use, a syntax error will occur
*/

   //no errors
   function Oh takesnothing
       call Foo()
    end
  
   function Foo takesnothing
    end
  
   //cyclical error
   function Boo takesnothing
       call Grow()
    end
  
   function Grow takesnothing
       call Boo()
    end
  
/*
*   Symbols that are not used anywhere are not included in code output.
*
*   ExecuteFunc and TriggerRegisterVariableEvent symbol use is checked.
*
*   Symbol use within strings handles string concatenation and variable use.
*   Variables that do not resolve to a known finite set of values will cause all symbols
*   that match the expression to be kept.
*
*   If only a variable from an unknown source is used, then all symbols will be kept
*/

   //kept
   function cheese34958493 takesnothing
    end
  
   //not kept
   function cheese31914 takesnothing
    end
  
   //kept
   function cheeseqa9a923 takesnothing
    end

   function oh takesnothing
       localstring str =GetEventPlayerChatString()
      
       callExecuteFunc("cheese"+ str +"3")
    end
  
/*
*   Both boolean and mathematical expressions are simplified
*/

   not a ornot b ->not(a and b)
   3*a +4*a ->7*a
   392+5->397
   3+3*a +3*b ->3*(1+ a + b)
  
/*
*   Lookup Operator (.)
*
*   Accesses members of a scope
*/

   scope a
       scope b
           integer o
        end
    end
  
   set a.b.o=4
  
   type m extendsintegerstaticinteger c
  
   set m.c=5
  
   scope a.b
       integer a
    end
  
   set a.b.a=5
  
   type m extendsintegerscope
       statictype o extendsintegerstaticinteger c
    end
  
   set m.o.c=11
  
/*
*   Scope Import, Export, Require
*
*   Require is used to make one scope require another scope's code
*   before being placed. This is used only for autorun code.
*/

   scope
        require b
      
       call Print("ran anonymous scope")
    end
  
   scope b
       call Print("ran b")
    end
  
   //
   //outputs
   //
   //  ran b
   //  ran anonymous scope
   //
  
/*
*   Import is used to import the symbols of a scope.
*
*   Import may either be static or non-static. Static will not
*   import virtual symbols. Virtual symbols can't be imported into a
*   non-type scope.
*
*   Import may also be global. Global will start at the global scope.
*/

   scope a
       integer p
    end
  
   scope b
        import a
      
       set p =4
    end
  
   type o scope
       staticinteger m
    end
  
   type z scope
       static import o //doesn't have to be static
      
       set m =5
    end
  
   scope h
       scope a
           integer q
        end
      
        global static import a
      
       set p =4//imported a from global scope, not local
    end
  
/*
*   Export is used to export the symbols from the scope to another scope
*
*   Export may be global and or static
*
*   Exported symbols may not be seen within the local scope.
*/

   scope c
       integer o
    end
  
   scope d
        global static export c
           integer q  //this q can see the scope it's in, but not the
                       //scope it's being exported to
                       //set o = 5 would not work
                       //set c.o = 5 would work
        end
      
       //this scope can't see q
       //set q = 4 would not work
       //set c.q = 4 would work
    end
  
   scope c
        require d //just to let people know that we now want d
                 //this isn't necessary, but it's a good practice
                
       set q =5//success
    end
  
/*
*   Symbols from a scope may only be imported into a scope once
*   The imported symbols are not copied!
*   The imported symbols can be shadowed
*/

   integer c =4
   integer c =4//syntax error, multiple definitions
  
   scope a
       integer c
       integer d
    end
  
   scope b
       integer c
       integer e
      
        global static import a
      
       set c =5//b.c
       set d =5//a.d
    end
  
/*
*   Static
*
*       A static member is a member that is linked to a type scope, the an
*       instance of a type scope.
*
*       A static symbol is a symbol that is not virtual.
*/

   type d extendsprivateintegerscope
       integer m //not static
       staticinteger o //static
    end
  
   set d.o=4//linked to scope
   set((d)1).m=4//linked to instance of scope
  
   //instances of a scope are also linked to the scope
   set((d)1).o=4
  
   //nothing in a type scope is static without the static keyword
  
   type d extendsprivateintegerscope
       statictype a extendsprivateinteger
       type a2 extendsprivateinteger//this is not static!
    end
  
   //example
    d test = new d()
  
    d.a test2 = new d.a()//linked to scope
    d.a2 test3 = new test.a2()//linked to instance of scope
  
   //if test were to be deleted, test3 would also be deleted
  
   //this is primarily used for closures (more on this later)
  
/*
*   Type Instance
*
*       A type is instantiated with the new operator.
*
*       The new operator calls the allocate function, which
*       returns an instance of the type.
*
*       If the new operator is overloaded, the default empty new operator
*       is removed.
*
*       If either the allocate or deallocate functions or overloaded, the
*       default of the other will be removed.
*/
  
   type test extendsprivateintegerscope
        override operator new takesinteger i
           setthis= allocate()
          
           returnthis
        end
      
        override operator delete
           call deallocate()
        end

       privatestaticinteger instanceCount =0
       privatestaticintegerarray recycler
       privatestaticfunction allocate takesnothing
           localinteger instance = recycler[0]
          
           if(instance ==0)then
               set instance = instanceCount +1
               set instanceCount = instance
           else
               set recycler[0]= recycler[instance]
            end
          
           return instance
        end
  
       privatefunction deallocate takesnothing
           set recycler[(integer)this]= recycler[0]
           set recycler[0]= recycler[(integer)this]
        end
    end
  
    test t = new test()//error, the default new operator was removed
  
/*
*   If new doesn't override, it will automatically call allocate
*
*   If delete doesn't override, it will automatically call deallocate
*   When delete doesn't override, the flow looks like this
*
*       call HiddenDeleteFunction(this)
*       call Delete(this)
*
*   The HiddenDeleteFunction will first call delete, then it will
*   deallocate.
*
*   The new operator works the same way in that it will allocate, call
*   the new function, then return the allocated instance
*/

   function Delete takesintegerthisreturnsnothing
       //user code
   endfunction
  
   function Deallocate takesintegerthisreturnsnothing
       //user code or default code
   endfunction

   //what is actually called when delete doesn't override
   function HiddenDeleteFunction takesintegerthisreturnsnothing
       call Delete(this)
       call Deallocate(this)
   endfunction
  
   function New takesintegerthisreturnsnothing
       //user code
   endfunction
  
   function Allocate takesnothingreturnsinteger
       //user code or default code
   endfunction
  
   //what is actually called
   function HiddenNewFunction takesnothingreturnsinteger
       localintegerthis= Allocate()
       //initialize fields
       call New(this)
       returnthis
   endfunction
  
/*
*   If delete isn't overloaded, Deallocate is called directly.
*
*   The new operator is *never* called directly. If it's not overloaded, then
*   it's just not called. If allocate isn't overloaded, then initialize fields
*   goes into allocate. If nothing is overloaded, allocate is called directly.
*
*   Unless override is used on new, the matching signature from the parent is called.
*   Unless allocate is overloaded, the allocate relies on parent's allocator.
*
*   The override keyword is used to stop the child type from calling the parent.
*   All functions in a type go through a dummy function that calls the parent before
*   going to the actual user function if a parent signature exists and it does something.
*/
  
   type a extendsprivateintegerscope
       integer o =3
      
       function Foo takesnothing
           set o =4
           set o =6
        end
      
       operator new takesnothing
           set o =9
           set o =10
        end
      
       operator delete
           set o =9
           set o =10
        end
    end
  
   type b extends a scope
       integer c =5
      
       function Foo takesnothing
           set o =7
           set o =8
        end
      
       operator new takesnothing
           set o =9
           set o =10
        end
      
       operator delete
           set o =9
           set o =10
        end
    end
  
   //translates to (actual code isn't readable)
   globals
       integerarray a_o
       integerarray b_c
   endglobals
  
   function A_Foo takesintegerthisreturnsnothing
       set a_o[this]=4
       set a_o[this]=6
   endfunction
  
   function A_New takesintegerthisreturnsnothing
       set a_o[this]=9
       set a_o[this]=10
   endfunction
  
   function A_Delete takesintegerthisreturnsnothing
       set a_o[this]=9
       set a_o[this]=10
   endfunction
  
   //allocate globals, other allocate code
   function A_Allocate takesnothingreturnsinteger
       //code
   endfunction
   function A_Deallocate takesnothingreturnsinteger
       //code
   endfunction
  
   function A_Hidden_New takesnothingreturnsinteger
       localintegerthis= A_Allocate()
       set a_o[this]=3
       call A_New(this)
       returnthis
   endfunction
  
   function A_Hidden_Delete takesintegerthisreturnsnothing
       call A_Delete(this)
       call A_Deallocate(this)
   endfunction
  
   function B_Foo takesintegerthisreturnsnothing
       set a_o[this]=7
       set a_o[this]=8
   endfunction
  
   function B_New takesintegerthisreturnsnothing
       set a_o[this]=9
       set a_o[this]=10
   endfunction
  
   function B_Delete takesintegerthisreturnsnothing
       set a_o[this]=9
       set a_o[this]=10
   endfunction
  
   function B_Hidden_New takesnothingreturnsinteger
       localintegerthis= A_Hidden_New()
       set b_c[this]=5
       call B_New(this)
       returnthis
   endfunction
  
   function B_Hidden_Delete takesintegerthisreturnsnothing
       call A_Delete(this)//no way around this chain
       call B_Delete(this)
       call A_Deallocate(this)
   endfunction
  
/*
*   Types can be used as variable types
*/

   type o extendsinteger
  
    o test
  
/*
*   They can be created and destroyed
*/

   set test = new o()
    delete test
  
/*
*   Non-static members can be accessed
*/

   type o extendsintegerinteger m
  
   set test = new o()
   set test.m=5
  
   type o extendsintegeroperator+ o c
       return(integer)this+(integer)c
    end
  
    o test2 = new o()
    o test3 = test + test2 //dangerous
  
/*
*   Out vs In
*
*   Out switches to the scope relating to the current scope
*   In switches back to the current scope
*/

    out scope
    end
  
    in scope
    end
  
    in integer i
    out integer i
  
/*
*   Example
*/

scope a
   function Foo takesnothing
       privateinteger i
    end
end

scope a
   function Foo takesnothing
       scope c
           call Print("hello")
        end
    end
end

scope d
   privateinteger n
  
    global static export a
        out scope//only way to combine with Foo inside of d
           function Foo takesnothing
               //in refers to d
               //out refers to caller of Foo
               //in.out refers to Foo
              
               //can't see i, can't see n
                in scope
                   //can see n now, but only because
                   //n is part of the origin scope
                   set n =5
                end
              
               //this is dangerous
                out
                   set f =6//any calling scope better see an f
                   call RunMe()//wtf?
                end
              
               call Print("what?")
              
                require c
            end
        end
    end
end

scope z
   integer f
  
   function RunMe takesnothing
       call Print("ran")
    end

   call a.Foo()
end

scope
   integer f
  
   function RunMe takesnothing
       call Print("ran again")
    end

   call a.Foo()
end

/*
*       Output
*
*           "ran"
*           "ran again"
*           "hello"
*           "what"
*
*       Results
*
*           z.f = 6
*           anon.f = 6 //the anonymous scope
*/

/*
*   Keep in mind that for merging scopes, the only fields that may not be
*   visible are private an internal.
*
*   Private will never be visible.
*
*   Internal will only be visible if the merging scope is in the same file or trigger.
*/

//this example is about as whacked as it gets
function foo takesnothing
    out set o =5
end
function t takesnothing
   integer o
  
   call foo()
  
   call Print(o)//prints 5
end

/*
*   One of the strangest examples ever
*   A way to return multiple variables
*/

function ReturnThis takesnothing
    out static export //no name needed
       integer i = out n
    end
end

scope
   function Woah takesnothing
       integer n =4
      
       while(n++<10) do
            ReturnThis()
            Print(i)           //5
                               //6
                               //7
                               //8
                               //9
                               //10
        end
    end
end

/*
*   Set
*
*   Set is used to explicitly require the = operator
*
*/

   set i =5

/*
*   It can only ever be used with the = operator
*
*   Without set
*/

    i =5
    i++
   ++i
    i /=5
  
/*
*   Call
*
*   Call is just an explicit function call. It may also be
*   implicit. As call does not really require anything, it
*   becomes an optional keyword.
*/

   call Foo()
    Foo()
  
/*
*   This fixes the special exceptions found in JASS
*/

   set i = Foo()//exception
  
   //should be
  
   set i =call Foo()//correct
  
   //by allowing call to be implicit, it fixes this exception
  
/*
*   Loops
*
*       for (integer i = 5, i < 4, ++4) do
*       end
*
*       while (i++ < 5) do
*       end
*
*       loop
*           while i++ < 5
*           exitwhen i++ >= 5
*       end
*
*       //overload the in operator
*       //overload the iterator operator
*       for (unit u in group) do
*       end
*/


JASS:
//inline
inline function Foo takesnothing//inline is forced
   return5
end

//symbols are kept from strings so long as they can be derived from that string statically
//this means only set-once variables that originate from literals
callExecuteFunc("${function Foo}")
callExecuteFunc((string)function Foo)

//runs preprocess code
preprocess
end

//debug only code
debug
end

//used inside of preprocess code to go back to script
script
end

//automatically determine signature of constant code
//anonymous function support
constantcode c =functiontakesnothing
               return5
            end

var i = c()

//use triggers for non-set once code
set c =functiontakesnothing
    end

call c()//trigger

//when no signature is provided, expects takes nothing returns nothing

function hi takesinteger i,integer i2 returnsinteger
   return i + i2
end

hi code c =   functiontakesinteger m,integer m2 returnsinteger
           return m*m2
        end

c =function hi

call c(5,6)//11

//virtual keyword may be applied to functions, operators, and properties within a type scope
//anything virtual will run off of triggers
virtual function Foo takesnothingreturnsnothing
end

type a extendsprivateinteger
virtual scope a link type a
    virtual function Foo takesnothingreturnsnothing
       return"a"
    end
end

type b extends a //public
virtual scope b link type b
    virtual function Foo takesnothingreturnsnothing
       return"b"
    end
end

a test1 = new a()
a test2 = new b()

call Print(test1.Foo())//"a"
call Print(test2.Foo())//"b"

//example of how scoping works

type a extendsprivateinteger

virtual scope o link type a
end

scope
   //access modifier on a one-liner refers to this scope
   //Foo is accessed from the target scope though
   private o function Foo takesnothing
    end
end

//The $ operator is used to interpolate things one level up
//string -> script -> preprocessor

string name ="hi"
call Print("$name")//prints hi

preprocess string name ="myVar" end
$name ="$$name"//myVar = "myVar"

loops
   loop
   forloop
   whileloop
    do whileloop

loop keywords
   exitwhen expression
    break
    continue

//example of some dynamic code with preprocess
preprocess
   typemodule

    virtual scopemodule link typemodule
       privatestatic dictionary<signature> flag = new dictionary<signature>()

       protected virtual function createScript takesnothingreturnsnothing
        end

       staticoperator new takes signature sig
           if(flag[sig])thenreturn(module)0

           call createScript()

           return(module)1
        end
    end
end

preprocess
   type mymodule extendsmodule

    virtual scope mymodule link type mymodule
       protected virtual function createScript takesnothingreturnsnothing
           integer i =0

           while(i <10)
                script
                   publicstaticstring str$i ="str$i"
                end
            end
        end
    end
end

type test extendsprivateinteger
virtual scope test link type test
    preprocess new mymodule(type test) end

   //the above creates 10 string variables, str0 through str9

   //attempting to run it a second time will do nothing
    preprocess new mymodule(type test) end
end

//templates are created with < > and can be applied types, functions, operators, and properties
//< > can accept signatures or labels
//
//the signature type is any signature
//
//template arguments are defined in both the preprocessor and the script and are constant

type<type T> test extendsprivateinteger//type T may also be made more explicit with extends
                     //for example, type T extends list, meaning that T must be
                     //a type of list, including list itself
                     //variable signatures are also accepted, like integer array VAR

virtual scope test link type test<type T>//signature includes the template
    T value
end

test<type integer> t = new test<type integer>()
set t.value=5


//The abstract keyword when applied to a type means that the type can't be used except for by other types.
//The sealed keyword when applied to a type means that the type can't be extended.
//The constant keyword when applied to a type means that all members of that type must be static and constant (like enums)
//when constant is applied to something, it can't change and it can only use constant code

//the super keyword is used in types to access the parent type

type a extendsprivateinteger
type b extendsprivate a

virtual scope a link type a
   function foo takesnothing
       return"a"
    end
end

virtual scope b link type b
   function foo takesnothing
       returnsuper.foo()//"a"
    end
end

//signature is a primitive type that holds signatures
//
//signatures include
//
//  function
//  scope
//  type
//  property
//  operator
//
//signatures can be used in various places
//the label of a signature can be used as a value (signaturetype label)
//the raw signature can also be used
//the signature type can be worked with like any other type
//
//the signature type includes the following functions and operators
//
//  (string)
//  scope //gets signature of enclosing scope
//  .exists //does the signature exist?
//
//the top level scope is called global
//
//an inlined function that is not simple enough to normally do inlining will create local variables
//to hold function calls

//closures

function rake takesnothing
   integer k =5

   function far takesnothing
       set k =6
    end

   call far()
   call Print(k)//prints 6

   callTimerStart(CreateTimer(),1,false,
           functiontakesnothing
               callDestroyTimer(GetExpiredTimer())
               call Print(k)//prints 9
            end)

   set k =9                            
end

//set takes an expression (it really should be evaluate..)
//
//set i++
//set i--

//integer forms
//
//     ascii: 'aaaaaaaaaaaaa'
//     hex: 0x5
//  octal: 01
//  binary: 0b1

//however, global and local variables don't really hold a place anymore

function rake takesnothing
   integer k =5//local variable

   //this is technically public, but it only exists for the lifetime of rake, so
   //it can't really be called outside of this instance of rake
   function far takesnothing
       //as no variables are copied, this just passes in the original closure
       //if there were new variables, it would create a new closure and give it old
       //closure + variables
       function far2 takesnothing
           call Print(k)
        end

       if(++k <10)then
           call far()
        end
    end

   integer i =4

   //a closure is created for this instance of rake
   //all locals used in far are copied to this closure
   //the closer is passed into far
   //far then uses the closure to work with the variables
   call far()

   //closure c = new closure(k)
   //call far(c)
   //  if (++c.k < 10) then call far(c) end
   //set k = c.k

   //i is not copied because far does not use it

   call Print(k)//prints 10

   //closures running on a timer or trigger or anything else are copied for those handles
   //via a hashtable
   callTimerStart(CreateTimer(),1,false,
           functiontakesnothing
               callDestroyTimer(GetExpiredTimer())
               call Print(k)//prints 9

               call far()//passes in closure that this function has
               //if there were multiple timers, triggers, and so on from this function, they'd
               //all share the same closure
            end)

   set k =9                            
end

//type nesting is the same way, except that rather than closures, types are passed in
//this is because the type itself can serve as a closure
//as such, a non-static type nested inside of a type must be created a special way

type outside extendsprivateinteger
virtual scope outside link type outisde
   type inside extendsprivateinteger
end

outside test = new outside()
outside.inside test2 = new test.inside()


//preprocessor includes object type, which works with objects
//object types include units, items, doodads, etc

unit footman =unit['hfoo']//access footman object

unit test = new unit('hfoo')//create a new object based on footman and return id
set test.life=5000//or w/e, properties are based off of object properties

//functions may take references
function hi takes reference integr i
   set i =5
end

integer i =4
call hi(i)//i is now 5

//  a virtual type is a type that can't be instantiated
//
//  type a extends private integer scope
//      virtual function oh takes nothing
//          call Print("a")
//      end
//  end
//
//  type b extends private integer scope
//      import a
//
//      virtual function oh takes nothing
//          call Print("b")
//      end
//  end
//
//  a test = new a()
//  a test2 = new b()
//
//  call test.oh() //prints "a"
//  call test2.oh() //error, not allocated
//
//  polymorpshim for function oh will still work under type b
//
//  type c extends private b scope
//      virtual function oh takes nothing
//          call Print("c")
//      end
//  end
//
//  b test3 = new c()
//  call test3.oh() //prints "c"
//
//  to use polymorphism, use extends or extensions
//
//  import will only import public symbols
//  extends and extensions will import public and protected symbols
//
//  .exists
//  .type
//  .signature
//  .super
//
//  a type may extend off of one non-virtual type
//  a type may extend off of many virtual types
//  a type may typecast to any type it extends from/to, including virtual types
//  a virtual type can't be typecasted to anything
//  types and virtual types can typecast to anything that they have an operator for
//  once a signature is virtual, it stays virtual
//  a signature may go from non-virtual to virtual
//  by default, methods will call super.method
//  in order to not call super.method, you may use the override keyword
//


Keep in mind that virtual symbols are defined in code block #2

This is an article on embedding languages
//o] is an expression?!
//how about it stops at ] and goes back to jass as ] isn't legal
//vjass either takes an expression or a statement!
//j vj j vj
set i[vjass o] = vjass 4

//this will be some hellish tokenization

//from a tokenizer point of view, when JASS sees vjass, what should the mode look like?
//it depends on where it's at, but the problem is that the tokenizer doesn't know where it's at
//so how about the tokenizer pushes modes whenever it enters a block such as a function?
//it pops modes whenever it hits ]
//this means that the following would tokenize
//j vj j
set o = vjass 5]

//let's conside this then
set i[vjass o]

//jass
//set i

//encounters [, so pushes jass mode
//but this depends on the mode we're in
//[

//push vjass
//vjass o

//pop vjass, now we're in jass
//pop jass, now we're still in jass
//]

//however, this would mean that for any token, it would have to do a look-ahead
//token {check for pops!}

//are there are smarter ways to do this?

//alternative solution is to have a standard set of tokens for all languages
//however, vjass 5] should still pop when it hits ]
//but this will mean that it won't need a look-ahead and ] will still just go to TOKEN__RBRACK
//instead of TOKEN__VJASS__RBRACK
//this would mean that there must be 1 tokens file, not 1 tokens file for each language
//tokens may not be used by a given language though

//whenever any language enters a delimited value, it pushes the current mode in
//whenever any langauge exits a delimited value, it pops
//this is already done for the values themselves, but not for [ ]
//so block statements would push/pop languages
//so should atoms push/pop values? no
//what about a string atom with complex interpolate operator? Still no, the $ operator would do it
//vjass itself won't pop until it sees a terminal or some sort of delimited closer

//j vj j
set i[vjass "foo"]

//the next problem is this
vjass function hi takes nothing returns nothing
endfunctoin

//by what was said previously
//vjass -> push vjass
//function -> push vjass
//endfunction -> pop vjass
//uh oh! this is where the terminal comes in, because remember vjass takes a statement
//\n -> pop vjass

//what about a language like cjass?
cjass void hi()
{
}

//cjass -> push cjass
//{ -> would normally push cjass, but what about the \n?
//we're in cjass atm, so it's expecting a ; terminal

//cjass -> push cjass
//{ -> push cjass
//} -> pop cjass
//uh oh, we're still in cjass!!
//; -> pop cjass

cjass void hi()
{
};

//so we're in cjass until we add a terminal?
//is this ok, or should } pop twice?
//perhaps check to see if it's expecting a terminal or not, then
//} can act as both a terminal and a function ender

//cjass -> push cjass, expecting terminal
//{ -> push cjass, not expecting terminal
//} -> pop cjass, check is expecting terminal, if it is, pop it again!
//this can actually be a loop, keep popping until you're not expecting a terminal

//now we can do this
cjass void hi()
{
}

//or this
//however, this is not good!
set i = cjass o; + 4

//this is smarter
//the ( ) is part of expressions, so it would push cjass and then pop it
//the ) is expectnig a terminal, so pop again
//then we get into the + 4
set i = cjass(o) + 4

//what about this?
cjass (integer i = 3)

//it would fail on the parser side as that's not a valid statement

//fails on the parser side, the [ ] is not valid here
set i = cjass[o] + 4

//this successed
set i = a cjass[o] + 4

//so then what if cjass gives a full terminal and it's expecting a terminal
//it's a terminal token!

set i = cjass (o) + 4
//-> set i = (o) + 4

//as can be seen, it will still produce a syntax error
//while the above won't
set i = cjass o; + 4
//-> set i = o
//+ 4

//this means that a statement can't end in either a language change or a terminal
//it must ALWYAS end in a termina
//if that language change includes a terminal, it will be used
//but what about things like }?
//the } can act as a terminal in cJASS!
//does this mean that we need to output a terminal token to play nice with the parser regardless of where we are with }?
//yes! the } by itself can't have two types, and cjass expects a { } while jass jass wants a \n

//but then wouldn't the following be valid?
cjass void hi() {
} set o = 4 //jass here

//so then perhaps } will pop twice like normal, then you can't put jass on the same line as the }

//so } should not output two tokens, it should not act as either a terminal or a }
//it is simply that cjass does not expect a terminal when it sees a }
//jass still wants its terminal regardless!
//what about something like this then?

set i = cjass o

//we're still in cjass down here, it wants a terminal
+ 5
+ 6;

//good!

//i believe that this offers the most flexibility and is the most logical



//now that we have organized the syntax from the lexer's point of view, it needs to be
//organized from the parer's point of view

//the parser must know where it's at at any given point of a statement, meaning statements
//must be broken up into many rules

//it is either that, or a cjass/vjass/etc token is only allowed at certain points, meaning that
//a statement won't need to be broken into oblivion

//where are these points valid then?

//at the start of any statement or within any expression?

//this means that there are in fact 5 scopes

//scope permanent
//scope global
//scope temporary
//scope action
//scope expression

//scope expression raises some other interesting points though
//set i = (integer b = 5)

//by rules of scoping, b would be visible outside of ( )

//to address scoping, we must ascertain what kind of visibility modifiers there are in JASS

//global anywhere
//local local to the scope
//none accessible through the scope (or anywhere if the scope is anonymous)

//if we follow these rules and apply them at any point, this will work out for JASS

//in cJASS, vJASS, etc, there are different properties
//public = none
//local = private
//protected
//internal
//friend

//this means that at any point in the parser, it must act on a language token depending on
//what type of scope it is in

//vjass doesn't take 1 statement, it takes 1 statement that is legal in the given scope that it wants

//so in reality, there are 5 different vjass things within JASS

//if it's in global, vjass can take a native, a type, or w/e
//if it's in temporary, vjass can only take certain other things

//I believe this ends the organization of both the lexer and the parser

































//how do we organize this for
// call vjass foo()
// ????

//need deeper rules!
// temporary scope function
//
// can't have temporary scopes
// can't have globals
// can't have natives/types
//
// permanent scope scope
//
// can't have natives/types
//
// action scope loop, if
//
// can't have temporary scopes
// can't have natives/types
//
// global scope
//
// anything

1 different environment for each language

use the special language construct tto access another environment/syntax

//the o,z,d are all from vjass environment
//everything up to the end of the statement is vjass
//the question is, how to have the terminal also be part of the jass statement
//unless a jass statement can end in either a code environment switch or a terminal
//which is smart
//so vjass should also be counted as a terminal
//jass o + vjass o + z + d
set i = o +

//doesn't allow one-liners :(
vjass
endvjass

vjass scope hi
endscope


function foo takes nothing returns nothing
vjass function boo takes nothing returns nothing //this shouldn't be allowed
endfunction //part of vjass still
//back to jass
endfunction

//a vjass function
//it's brilliant :O, cuz vjass is like a modifier here
vjass function foo takes nothing returns integer
return 5
endfunction

//another foo
//because each language
function foo takes nothing returns nothing
endfunction

//call foo from vjass
set i = vjass foo()
vjass call foo()
call foo()

//jass cjass jass
set i = o + cjass i; set c = i
 

tom_mai78101

The Helper Connoisseur / Ex-MineCraft Host
Staff member
Reaction score
1,672
I'm sorry, but your point is? You are explaining what ReturnThis does in a loop, but you never explain why call on ReturnThis function or what's special about it. Just the export, static, and out keywords?

And then you mentioned to take a look at the notes, which is relevant to ReturnThis? Maybe a concise form of abstract is suffice, considering how long I have to read.

A more cleaner version of the article would be nice. It is currently riddled with slanted lines and a few spelling errors, which I'm sure there is room for improvements.
 
Last edited:
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Varine Varine:
    I want to build a filtration system for my 3d printer, and that shit is so much more complicated than I thought it would be
  • Varine Varine:
    Apparently ABS emits styrene particulates which can be like .2 micrometers, which idk if the VOC detectors I have can even catch that
  • Varine Varine:
    Anyway I need to get some of those sensors and two air pressure sensors installed before an after the filters, which I need to figure out how to calculate the necessary pressure for and I have yet to find anything that tells me how to actually do that, just the cfm ratings
  • Varine Varine:
    And then I have to set up an arduino board to read those sensors, which I also don't know very much about but I have a whole bunch of crash course things for that
  • Varine Varine:
    These sensors are also a lot more than I thought they would be. Like 5 to 10 each, idk why but I assumed they would be like 2 dollars
  • Varine Varine:
    Another issue I'm learning is that a lot of the air quality sensors don't work at very high ambient temperatures. I'm planning on heating this enclosure to like 60C or so, and that's the upper limit of their functionality
  • Varine Varine:
    Although I don't know if I need to actually actively heat it or just let the plate and hotend bring the ambient temp to whatever it will, but even then I need to figure out an exfiltration for hot air. I think I kind of know what to do but it's still fucking confusing
  • The Helper The Helper:
    Maybe you could find some of that information from AC tech - like how they detect freon and such
  • Varine Varine:
    That's mostly what I've been looking at
  • Varine Varine:
    I don't think I'm dealing with quite the same pressures though, at the very least its a significantly smaller system. For the time being I'm just going to put together a quick scrubby box though and hope it works good enough to not make my house toxic
  • Varine Varine:
    I mean I don't use this enough to pose any significant danger I don't think, but I would still rather not be throwing styrene all over the air
  • The Helper The Helper:
    New dessert added to recipes Southern Pecan Praline Cake https://www.thehelper.net/threads/recipe-southern-pecan-praline-cake.193555/
  • The Helper The Helper:
    Another bot invasion 493 members online most of them bots that do not show up on stats
  • Varine Varine:
    I'm looking at a solid 378 guests, but 3 members. Of which two are me and VSNES. The third is unlisted, which makes me think its a ghost.
    +1
  • The Helper The Helper:
    Some members choose invisibility mode
    +1
  • The Helper The Helper:
    I bitch about Xenforo sometimes but it really is full featured you just have to really know what you are doing to get the most out of it.
  • The Helper The Helper:
    It is just not easy to fix styles and customize but it definitely can be done
  • The Helper The Helper:
    I do know this - xenforo dropped the ball by not keeping the vbulletin reputation comments as a feature. The loss of the Reputation comments data when we switched to Xenforo really was the death knell for the site when it came to all the users that left. I know I missed it so much and I got way less interested in the site when that feature was gone and I run the site.
  • Blackveiled Blackveiled:
    People love rep, lol
    +1
  • The Helper The Helper:
    The recipe today is Sloppy Joe Casserole - one of my faves LOL https://www.thehelper.net/threads/sloppy-joe-casserole-with-manwich.193585/
  • The Helper The Helper:
    Decided to put up a healthier type recipe to mix it up - Honey Garlic Shrimp Stir-Fry https://www.thehelper.net/threads/recipe-honey-garlic-shrimp-stir-fry.193595/
  • The Helper The Helper:
    Here is another comfort food favorite - Million Dollar Casserole - https://www.thehelper.net/threads/recipe-million-dollar-casserole.193614/

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top