- Joined
- Jul 10, 2007
- Messages
- 6,306
I need to collect some feedback from the general community about what features people want. I was originally going to focus on doing vJASS, but I decided to save it for later since it's such a mess and just do what I call xJASS, known as extended JASS. Keep in mind that I will add vJASS later on. For now I'd rather have a clean language that follows the JASS paradigm.
If we look at the JASS syntax, there are only a few things. I propose to take the original syntax and extend it without deforming it.
The first extension I propose is the addition of the scope, much like in vJASS. However, scopes may require other scopes. Requirements define the order of initialization.
The next point is that all variables within scopes are by default public. To access variables, the resolution operator "." is used
A major point of contention is whether to use the public/protected/private/internal scheme or the nothing/local scheme. JASS uses the nothing/local scheme. It's essentially either public or it's protected. If we are to follow JASS syntax as closely as possible, even though we are losing some possible encapsulation features, I think that the nothing/local thing should be used.
The next point of contention is the globals block. In JASS, there may only ever be one globals block and this block contains all global variables. I propose to simply do away with it and hide it in the background, much like main and config. The alternative would be opening up main and config to the user like in c++, doing away with requirements, and having the user define everything in their map. Let's not do that.
The next point is how to handle structs from vJASS. I propose to use the type syntax that JASS provides. A type can be declared, but how are fields added to it?
Something like the following would be nice. However, JASS types are by default 1 liners.
I propose then that a new scope syntax should be introduced to work with types.
It would also valid to do this. You would no longer be able to do this.functionName as the scope would be static.
The next point is the order of initialization for merged scopes. I propose a secondary id. The secondary id is defined to be the same as the first id when it's not used. The secondary id is what is actually used for requirements.
When two scopes happen to have the same secondary id, the order of initialization for them can't be defined.
My next proposition is to define initialized code as code that's not in a function. The code runs down the scope in order.
A new Hello World example
Next I propose code reordering based on usage.
Initialized code can't access each other, so their order is defined solely by scope requirements. If you don't care about initialization order, then you don't need to ever use scope requirements.
Next, I propose operator overloading in the following manner. Operators can be local and can be scoped as well.
I also propose getters and setters.
I also propose typecasting
The next point I'd like to address is polymorphism. JASS types are not polymorphic. You can't remove a widget, or a handle. You must remove the specific type. As such, I propose to add a new polymorphic keyword.
Everything extending from a polymorphic type must be polymorphic. The base type need not be polymorphic. However, destroying the base type will not destroy the polymorphic type correctly.
Next, I propose the inline keyword
I propose the following. It would use a boolexpr array and give each function used like this a unique id that corresponds to the array. I also propose that we allow calling all executable variables like a regular function.
I propose function overloading and variable shadowing. I propose that the "." operator, when used by itself, accesses the outer scope.
The next point to cover is preprocessing.
I believe that # should execute preprocessor code and that $ should execute preprocessor code and then dump the result to the script. From the preprocessor side, $ should evaluate a script expression and dump it to the preprocessor. From the string side, $ execute script code and dump it to the string. A $$ would evaluate preprocessor code in a string. I propose that the preprocessor syntax be the same as the xJASS syntax and that xJASS scopes exist both in the preprocessor and in xJASS. Any constant expressions in xJASS also exist in the preprocessor and can be accessed with the $ operator. The # also interpolates.
I also propose preprocessor scopes.
I propose the break statement, the while loop, the for loop, and the do while loop. I also propose that the preprocessor has access to the map archive objects and what not.
I propose that xJASS have an import keyword. Things may be imported publicly or locally.
I propose an include keyword in the preprocessor, which would include files. The files can be imported as many times as one likes. I propose an import count variable, which counts how many times a given file has been imported.
I propose that preprocessor functions be able to tell what scope they are currently running inside of, both by primary and secondary id. This will allow us to implement modules.
I propose lambda expressions
I believe that this language is much cleaner than vJASS and follows the JASS paradigm closely. If anyone would recommend any changes, additions, or deletions, please let me know.
I'll eventually put together a manual with the community consensus on what the language should look like.
Now, keep in mind... I love public/protected/private/internal. I really like that fine control over encapsulation. I personally want them, but I know that JASS just uses local. We could possibly say that local is protected internal (translated over) and then add the other stuff : O.
edit
I propose a special preprocessor variable of type script. Script variables can be added to or set. Their contents are dynamically placed in the script.
If we look at the JASS syntax, there are only a few things. I propose to take the original syntax and extend it without deforming it.
JASS:
// comments
type typeName [extends typeName]?
[local]? [constant]? typeName [array]? variableName
exitwhen expression
return expression
set variableName = expression
call functionName(...)
[constant]? function functionName takes ... returns ...
endfunction
if expression then
endif
loop
endloop
globals
endglobals
function main...
function config...
The first extension I propose is the addition of the scope, much like in vJASS. However, scopes may require other scopes. Requirements define the order of initialization.
JASS:
scope [name]? [requires ...]?
endscope
The next point is that all variables within scopes are by default public. To access variables, the resolution operator "." is used
JASS:
scope MyScope
integer thisIsPublic
endscope
set MyScope.thisIsPublic = 6
A major point of contention is whether to use the public/protected/private/internal scheme or the nothing/local scheme. JASS uses the nothing/local scheme. It's essentially either public or it's protected. If we are to follow JASS syntax as closely as possible, even though we are losing some possible encapsulation features, I think that the nothing/local thing should be used.
JASS:
scope MyScope
integer thisIsPublic
local integer thisIsLocal = 7
endscope
set MyScope.thisIsPublic = 6
set MyScope.thisIsLocal = 9 //error!
The next point of contention is the globals block. In JASS, there may only ever be one globals block and this block contains all global variables. I propose to simply do away with it and hide it in the background, much like main and config. The alternative would be opening up main and config to the user like in c++, doing away with requirements, and having the user define everything in their map. Let's not do that.
The next point is how to handle structs from vJASS. I propose to use the type syntax that JASS provides. A type can be declared, but how are fields added to it?
Something like the following would be nice. However, JASS types are by default 1 liners.
JASS:
type myType extends integer
endtype
I propose then that a new scope syntax should be introduced to work with types.
JASS:
type myType extends integer
// the scope is no longer static
scope this.myType
function this.functionName takes nothing returns nothing
endfunction
endscope
It would also valid to do this. You would no longer be able to do this.functionName as the scope would be static.
JASS:
type myType extends integer
scope myType
function functionName2 takes nothing returns nothing
endfunction
endscope
scope this.myType
function functionName takes nothing returns nothing
call functionName2()
endfunction
endscope
The next point is the order of initialization for merged scopes. I propose a secondary id. The secondary id is defined to be the same as the first id when it's not used. The secondary id is what is actually used for requirements.
When two scopes happen to have the same secondary id, the order of initialization for them can't be defined.
JASS:
// runs either first or second
scope MainScope
function functionName2 takes nothing returns nothing
endfunction
endscope
// runs either first or second
scope MainScope
function functionName3 takes nothing returns nothing
endfunction
endscope
// runs third
scope MainScope as UniqueScopeName requires MainScope
// just showing local keyword on a function
local function functionName takes nothing returns nothing
call functionName2()
call functionName3()
endfunction
endscope
My next proposition is to define initialized code as code that's not in a function. The code runs down the scope in order.
A new Hello World example
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60000, "Hello World!")
Next I propose code reordering based on usage.
JASS:
function A takes nothing returns nothing
call B() //B is put ahead of A because A uses it
endfunction
function B takes nothing returns nothing
endfunction
Initialized code can't access each other, so their order is defined solely by scope requirements. If you don't care about initialization order, then you don't need to ever use scope requirements.
Next, I propose operator overloading in the following manner. Operators can be local and can be scoped as well.
I also propose getters and setters.
JASS:
// order doesn't matter
operator function + takes integer i, string s returns string
return I2S(i) + s
endfunction
// careful
operator function this.+ takes string s returns string
endfunction
operator function [] takes integer i returns integer
endfunction
// dynamic
operator function[][][,][][][,,] takes ... returns integer
endfunction
operator function this.[][][][][,,] takes ... returns integer
endfunction
getter function i takes nothing returns integer
return someVar
endfunctoin
setter function i takes integer m returns nothing
set someVar = m
endfunction
// create
operator function this.new takes nothing returns someType
endfunction
// allocate
operator function this takes nothing returns someType
endfunction
// destroy
operator function this.delete takes nothing returns nothing
endfunction
set i = 5
string s = i + "moo"
I also propose typecasting
(type)myVar
The next point I'd like to address is polymorphism. JASS types are not polymorphic. You can't remove a widget, or a handle. You must remove the specific type. As such, I propose to add a new polymorphic keyword.
polymorphic type myType extends integer
Everything extending from a polymorphic type must be polymorphic. The base type need not be polymorphic. However, destroying the base type will not destroy the polymorphic type correctly.
Next, I propose the inline keyword
JASS:
inline function hello takes nothing returns nothing
endfunction
I propose the following. It would use a boolexpr array and give each function used like this a unique id that corresponds to the array. I also propose that we allow calling all executable variables like a regular function.
JASS:
function myFunction takes nothing returns nothing
endfunction
function ohNo takes functionid func returns nothing
call func()
endfunction
call ohNo(myFunction)
I propose function overloading and variable shadowing. I propose that the "." operator, when used by itself, accesses the outer scope.
The next point to cover is preprocessing.
I believe that # should execute preprocessor code and that $ should execute preprocessor code and then dump the result to the script. From the preprocessor side, $ should evaluate a script expression and dump it to the preprocessor. From the string side, $ execute script code and dump it to the string. A $$ would evaluate preprocessor code in a string. I propose that the preprocessor syntax be the same as the xJASS syntax and that xJASS scopes exist both in the preprocessor and in xJASS. Any constant expressions in xJASS also exist in the preprocessor and can be accessed with the $ operator. The # also interpolates.
I also propose preprocessor scopes.
JASS:
constant integer i = 3
#integer m = 2
#scope //preprocessor
if (true)
//dumped to script
#scope //script
endscope
else
//not dumped to script
#scope //script
endscope
endscope
print($i) //prints 3
endscope
#set m = 9
print($m) //prints 9
print("$i") //prints 3
print("$$m") //prints 9
print("\$i") //prints $i
I propose the break statement, the while loop, the for loop, and the do while loop. I also propose that the preprocessor has access to the map archive objects and what not.
I propose that xJASS have an import keyword. Things may be imported publicly or locally.
I propose an include keyword in the preprocessor, which would include files. The files can be imported as many times as one likes. I propose an import count variable, which counts how many times a given file has been imported.
JASS:
#if (FILE_IMPORT != 1) then
return
endif
// script
I propose that preprocessor functions be able to tell what scope they are currently running inside of, both by primary and secondary id. This will allow us to implement modules.
I propose lambda expressions
JASS:
functionid c = function() endfunction
I believe that this language is much cleaner than vJASS and follows the JASS paradigm closely. If anyone would recommend any changes, additions, or deletions, please let me know.
I'll eventually put together a manual with the community consensus on what the language should look like.
Now, keep in mind... I love public/protected/private/internal. I really like that fine control over encapsulation. I personally want them, but I know that JASS just uses local. We could possibly say that local is protected internal (translated over) and then add the other stuff : O.
edit
I propose a special preprocessor variable of type script. Script variables can be added to or set. Their contents are dynamically placed in the script.
JASS:
#script i
$i
#set i = i + "hi"
#set i = "o"
// everywhere i is used will be "o", even if it was used before it was changed
Last edited: