• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

vrJASS

Status
Not open for further replies.
Level 10
Joined
Sep 19, 2011
Messages
527
So I began to work on the standard library (providing tests, that's why) (won't be that big though) and I would like to ask you guys what do you think of this:

JASS:
struct DoublyLinkedListTest
    static method onInit
        local List.Doubly dll = List.Doubly.allocate()
        
        local Object a = Object.allocate()
        local Object b = Object.allocate()
        local Object c = Object.allocate()
        local Object d = Object.allocate()
                
        call dll.insert(a)
        call Assert.instance(dll.getHead(), a, 11)
        call Assert.instance(dll.getLast(), a, 12)
        
        local List.Iterator it = dll.createIterator()
        
        call Assert.toBeTrue(it.hasNext(), 16)
        call Assert.instance(a, it.getNext(), 17)
        call Assert.toBeFalse(it.hasNext(), 18)
        
        call dll.insert(b)
        call dll.insert(c)
        
        set it = dll.createIterator()
        
        call Assert.instance(it.getNext(), a, 25)
        call Assert.instance(it.getNext(), b, 26)
        call Assert.instance(it.getNext(), c, 27)
    endmethod
endstruct

(The integer argument is the line of the source code and I know, I should burn in hell but I'm too lazy to make some special crazy sh*t on the compiler :3)

If anything fails, the messages printed look like this:

fail.jpg

Why no custom message when failing?, I found it pretty useless :grab popcorn:.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Uhm, inserting the line numbers by hand is ... ... I can find an error with less hassle and almost as quickly by identifying the thing that failed.

You likely want to do a DEBUG_MODE and then a hidden lineNumber variable. Between every line, set this variable to the following line number (do not increment it). Notice this example is also intelligent. It doesn't set the line number for empty lines. The local integer is also going to be based on the actual line number in the trigger or file. It's not going to be a 1.

JASS:
local integer ahffhfh32 = 1
loop
    set ahffhfh32 = 2
    call DisplayTimedTestToPlayer(GetLocalPlayer(), 0, 0, 60, "meh")

    set ahffhfh32  = 4
    exitwhen true
endloop

You also need to identify which folder/trigger or file failed.

Error - FolderName/TriggerName #Line Failed

You also need to have error messages for why it failed. The best way is to allow throw( ) and try/catch. Think of my little error library for memory. It can detect double frees, memory leaks, and so on. It can also analyze allocators.
 
Level 10
Joined
Sep 19, 2011
Messages
527
Uhmm, now that I think, it is useful as you say to attach the name of the scopes (like <library>.<function> ...).

The line by hand is because I haven't figured out how could I get the correct line when you're coding from NewGen (because it adds the map code too).

edit:

call Assert.create("DoublyLinkedList").onLine(11).toBeInstance(dll.getHead(), b)

will be shorted to: call assert("...").onLine(...).toBeInstance(...)
 
Last edited:
Level 10
Joined
Sep 19, 2011
Messages
527
Update:

e8b22a7 Add validation for break statement (check if it is being used inside of loop)
d05ee7e Implement 'break' statement
b1ac4b8 Implement while loop
d3c0365 Implement 'end' as an alternative to endfunction, endif, etc.
475d671 Add 'not' translation
bf36467 Add function code translation
 
Level 11
Joined
Dec 19, 2012
Messages
411
Porbably, like this :
JASS:
set i = 0

loop
    exitwhen i > 10
    if i == 5 then
      continue
    endif
    call BJDebugMsg("value of i : " + I2S(i))
    set i = i + 1
endloop

after complied, will become :
JASS:
set i = 0

loop
    exitwhen i > 10
    if not (i == 5) then
      call BJDebugMsg("value of i : " + I2S(i))
    endif
    set i = i + 1
endloop
or
JASS:
set i = 0

loop
    exitwhen i > 10
    if (i == 5) then
    else
      call BJDebugMsg("value of i : " + I2S(i))
    endif
    set i = i + 1
endloop
 
Level 6
Joined
Jul 30, 2013
Messages
282
very excited bout the new progress :)

hmm whats the vjass/cjass integration story tho? will it ever be feasible for this to fully replace vjass? or would using this in an existing project just end up making the setup even more fragile?
 
Level 10
Joined
Sep 19, 2011
Messages
527
Update:

I decided not to implement modules. Why?, because they're not needed and their utility can be reached by using oop (inheritance or even a simple property).

Also, auto-local-null won't be added since optimizers (as far as I know) already do this.

Edit:

I was also going to implement define, but since cjass does a pretty good job on them I've decided to delegate to it.
 
Last edited:
Level 10
Joined
Sep 19, 2011
Messages
527
hii pp, so far i've been testing vrjass developing its standard library and i'm impressed about how well it is responding. so far i've only found little details (mainly oop stuffs) that i'm polishing.

in a few days i'm going to be uploading a new version and i think i will be working on the manual (which is going to be uploaded to github/wiki).
 
Level 10
Joined
Sep 19, 2011
Messages
527
little announcement: after releasing an stable version i will change the direction of the language. at the beginning i liked the idea of having something like java... but then i realize that it is kinda shitty because it restricts the user way too much into thinking/work the way i would. so what i would like now is -in simple terms- give the user flat freedom (kinda like c or javascript).
 
Level 10
Joined
Sep 19, 2011
Messages
527
ok pp hopefully this is the last release candidate. i would really like if you could test it (make some damage system, timers, those who you really enjoy xD) and report bugs if you find them. thanks!

https://github.com/Ruk33/vrJASS/releases/tag/v2.1.0-rc

if you need some examples, i will leave you with the std library:

JASS:
struct Object
    static integer instances
    
    public static method allocate takes nothing returns Object
        set Object.instances += 1
        return Object.instances cast Object
    endmethod
    
    public method equals takes Object e returns boolean
        return this == e
    endmethod
    
    public method isNull returns boolean
        return this == null
    endmethod
    
    public method toString returns string
        return I2S(this cast integer)
    endmethod
endstruct

JASS:
interface Collection
	public method contains takes Object e returns boolean
	public method createIterator returns List.Iterator
endinterface

JASS:
struct Array extends Object implements Collection

	integer size

	Object array elements
	integer array indexes
	
	List.Doubly list
	
	public method get takes integer index returns Object
		return this.elements[index]
	endmethod
	
	public method add takes integer index, Object e
		set this.size += 1
		
		set this.elements[index] = e
		set this.indexes[e] = index
		
		call this.list.insert(e)
	endmethod
	
	public method remove takes Object e returns nothing
		if (this.getSize() == 0) then
			return
		endif
	
		local integer index = this.indexOf(e)
	
		if (index == -1) then
			return
		endif
		
		set this.size -= 1
		
		set this.elements[index] = null
		set this.indexes[e] = -1
		
		call this.list.remove(e)
	endmethod
	
	public method contains takes Object e returns boolean
		return this.indexOf(e) != -1
	endmethod
	
	public method getSize takes nothing returns integer
		return this.size
	endmethod
	
	public method createIterator returns List.Iterator
		return this.list.createIterator()
	endmethod
	
	public method indexOf takes Object e returns integer
		local integer index = this.indexes[e]
		
		if (this.elements[index].equals(e)) then
			return index
		endif
		
		return -1
	endmethod
	
	public static method create returns Array
		local Array instance = Array.allocate()
		set instance.list = List.Doubly.allocate()
		return instance
	endmethod

endstruct

JASS:
struct Stack extends Object implements Collection

	Array elements
    
	public method push takes Object e
		call this.elements.add(this.elements.getSize(), e)
	endmethod
	
	public method peek returns Object
		return this.elements.get(this.elements.getSize()-1)
	endmethod
	
	public method pop returns Object
		local Object e = this.peek()
		call this.elements.remove(e)
		return e
	endmethod
	
	public method contains takes Object e returns boolean
		return this.elements.contains(e)
	endmethod
	
	public method createIterator returns List.Iterator
		return this.elements.createIterator()
	endmethod
	
endstruct

JASS:
struct Queue extends Object implements Collection

	List.Doubly elements

	public method enqueue takes Object e
		call this.elements.insert(e)
	endmethod
	
	public method dequeue returns Object
		local Object e = this.elements.getHead()
		call this.elements.remove(e)
		return e
	endmethod
	
	public method contains takes Object e returns boolean
		return this.elements.contains(e)
	endmethod
	
	public method createIterator returns List.Iterator
		return this.elements.createIterator()
	endmethod
	
	public static method create returns Queue
		local Queue instance = Queue.allocate()
		set instance.elements = List.Doubly.create()
		return instance
	endmethod

endstruct

JASS:
library List

    struct Node extends Object
	
        Object element
        Node prev
        Node next
		
		public method destroy
			set this.prev.next = this.next
			set this.next.prev = this.prev
		endmethod
        
        public method getElement returns Object
            return this.element
        endmethod
        
        public method getPrev returns Node
            return this.prev
        endmethod
        
        public method getNext returns Node
            return this.next
        endmethod
        
        public static method create takes Node prev, Object element, Node next returns Node
            local Node new = Node.allocate()
			
            set new.element = element
			
			if (prev.isNull()) then
				set prev = new
			endif
			
			if (next.isNull()) then
				set next = new
			endif
			
			set new.prev = prev
			set new.next = next
			
			set prev.next = new
			set next.prev = new
            
            return new
        endmethod
		
    endstruct
    
    public struct Doubly extends Object implements Collection
	
        Node master
		Node array nodes
		        
        public method createIterator returns Iterator
            return Iterator.create(this.master)
        endmethod
		
        public method getHead returns Object
            return this.master.getNext().getElement()
        endmethod
        
        public method getLast returns Object
            return this.master.getPrev().getElement()
        endmethod
		
		public method insertBefore takes Object before, Object e
			local Node beforeNode = this.nodes[before]
			
			if (beforeNode.isNull()) then
				set beforeNode = this.master
			endif
			
			set this.nodes[e] = Node.create(beforeNode.getPrev(), e, beforeNode)
		endmethod
		
		public method insertAfter takes Object node, Object e
			call this.insertBefore(this.nodes[node].getNext().getElement(), e)
		endmethod
		
        public method insert takes Object e
			call this.insertAfter(this.master.getPrev().getElement(), e)
        endmethod
		
		public method remove takes Object e
			call this.nodes[e].destroy()
		endmethod
		
		public method contains takes Object e returns boolean
			return this.nodes[e].isNull() == false
		endmethod
		
		public static method create returns Doubly
			local Doubly instance = Doubly.allocate()
			set instance.master = Node.create(null, null, null)
			return instance
		endmethod
		
    endstruct
    
    public struct Iterator extends Object
	
        Node head
		Node node
		
		public method reset
			set this.node = this.head
		endmethod
        
        public method hasNext returns boolean
            return this.node.equals(this.head)
        endmethod
        
        public method getNext returns Object
            set this.node = this.node.getNext()
			return this.node.getElement()
        endmethod
    
        public static method create takes Node node returns Iterator
            local Iterator it = Iterator.allocate()
            
            set it.head = node
            set it.node = node
            
            return it
        endmethod
		
    endstruct

endlibrary
 
Level 10
Joined
Sep 19, 2011
Messages
527
Improve is type compatible check on user defined types
https://github.com/Ruk33/vrJASS/commit/1e48870896054b1c810ab8a654384281666d66b5

cya!

edit: debugging like a boss:

YihcRSL.png


i was also able to fix a few translation bugs (although now initalizers are not placed in main, in tests they work but in maps dont <.< fixed).

https://github.com/Ruk33/vrJASS/commit/9e15e5521695d451e0d16ab871f56e6407175fad
https://github.com/Ruk33/vrJASS/commit/83e5098fdb9e3e588e5094a83e613b83189d6ea9
https://github.com/Ruk33/vrJASS/commit/7783187e261231b4d291466b66c2d024e00c2fab
 
Last edited:
Level 10
Joined
Sep 19, 2011
Messages
527
Implementing interfaces (like a boss, yes, everything has to be like a boss)

So I just figured out that interfaces are broken in vrjass because it fails here https://github.com/Ruk33/vrJASS/issues/17.

How would YOU implement them?

My approach would be through instance type.

For example, we have an struct A, B and C. A has a type of 1, B is 2 and finally C 3. When an interface method is called, it will check which instance type it is and execute accordingly:

JASS:
function interface_method takes Object this, ... returns ...
    if (this._type == 1) then // A
        call interface_method_of_a(this, ...)
    elseif (this._type == 2) then // B
        call interface_method_of_b(this, ...)
    elseif (this._type == 3) then //C
        call interface_method_of_b(this, ...)
    endif

It is quite probably that there wont be that many implementations of an interface so this massive if shouldn't be a problem.

What do you guys think?.
 
Level 13
Joined
Nov 7, 2014
Messages
571
One thing that could justify the addition of such a feature would be the fact that this "pattern" turns out to
be very common in jass (I don't think it is, but I could be wrong of course). One way to find out if it is common
would be to look at (search for this patter or equivalent) a decent amount of code people have written over the years.

Or you could just add a ternary op which is more general (blizzard made a version for integers for it: IntegerTertiaryOp),
but then again it's your compiler.

From a while back:
Hi pp, I would like to implement the continue statement for loops but I don't have a clue of how the translation (raw jass) could look like, can you help me? thanks.

JASS:
local integer i

set i = 1
loop
    exitwhen i > 9

    if i == 3 then
        continue
    endif

    if i == 5 then
        continue
    endif

    call BJDebugMsg(I2S(i))

    set i = i + 1
endloop

=>

JASS:
local integer i
local boolean continue

set i = 1 - 1
loop
    set continue = false

    loop
        set i = i + 1
        exitwhen i > 9

        if i == 3 then
            set continue = true
            exitwhen true
        endif

        if i == 5 then
            set continue = true
            exitwhen true
        endif

        call BJDebugMsg(I2S(i))
    endloop

    exitwhen not continue
endloop

At least that's the code I would write by hand if I wanted a emulate a continue statement.
 
Last edited:
Level 10
Joined
Sep 19, 2011
Messages
527
@PurgeandFire ye it might be (although I really enjoy using it on Javascript). I'll still see if the comunity says something else.

@Aniki I really like your translation, I also found the same on Stackoverflow so I think I'll go with that.

Btw, suggestions/comments on features are welcome ^^
 
Last edited:
Level 10
Joined
Sep 19, 2011
Messages
527
Last edited:
Level 10
Joined
Sep 19, 2011
Messages
527
I really liked the SublimeText lint stuff so I've adapted the compiler to get better results.

Previously the compiler was writing a lot in the disk even if we didn't ask for the translated code or the log. This made the lint a little bit slower, so now no translated code or logs if we don't ask for them.
https://github.com/Ruk33/vrJASS/commit/e151039ce15b1cc6127b66169b1e5bac5fdf33de

I haven't read that much about how the lint works. The first thing that I saw was that it takes the input of the console so now the compiler allow you to write in the console if you pass the argument "-c".
https://github.com/Ruk33/vrJASS/commit/299a3ac68993e973c3703c087e280c4ea2252632

And then, while I was playing on the editor, I had a few errors on interfaces (return type checks).
https://github.com/Ruk33/vrJASS/commit/5e5f7735fb93626a73e76fe96f40c9b92a6b28bd
https://github.com/Ruk33/vrJASS/commit/ee282692b77f4a3e2e91ba064d1744a7e80dc163

The next thing that I'm going to be fixing is method overwriting in classes:

JASS:
struct foo
  public method hi
    call BJDebugMsg("hi from foo")
  endmethod
endstruct

struct bar extends foo
  public method hi
    call BJDebugMsg("hi from bar")
  endmethod
endstruct

local foo instance = bar.create()
call instance.hi() // will display hi from foo, it should be bar

After this, I think it is ready for stable version ^^.

Bye!
 
Level 13
Joined
Nov 7, 2014
Messages
571
I personally would try to avoid tools that slow down map compilation speeds and thus iterations speed, because I can't get anything right
the first time and I have to rewrite, fix mistakes and recompile/reload the map many many times. This funny enough includes jasshelper and it's (11+ "phases" of compilation) but I try to avoid some of those (textmacros, unnecessary calls to external commands (ObjectMerger), not having that much code in the first place).

cJass is crazy fast (it's written in assembly!!??), I can barely see it's progress bar.

vrJass is written in Java and it's startup time is "much slower".
 
Level 25
Joined
Feb 2, 2006
Messages
1,689
Hey this seems very interesting but I would have prefered just bug fixes of vJass.

Is this fully compatible to vJass?

You know there is a huge list of problems in vJass. Some of them are linked here: http://wc3lib.org/vjass.html

Of course there is Wurst but my project uses a very big amount of vJass code, so an improved compiler would really help. If your compiler does already support the old vJass you could rather work on fixing these bugs. For example I cannt override a stub method if it is not from the direct base struct but from the parent struct of the base struct.

I think cohadar (don't know if it is spelled correctly) tried to improve the JassHelper but I have not tested his version yet.

An improved vJass compiler would really help my project.

One major improvement would be to show more than one single error message. Is this the case for this compiler?
 
Level 10
Joined
Sep 19, 2011
Messages
527
Thanks @Barade, that is a great link collection.

About compatibility I've tried to support as many as I could. So far no major changes are required (a few keywords, the use of dot instead of underscore, etc.) but I do have to implement a few more features of vJASS (like modules, yes I'm gonna implement them just lo learn how).

I also though about showing more than 1 error, but I kinda like to do 1 thing at a time and throwing only one allows you to do exactly that, you only focus on that particularly error.
 
Level 19
Joined
Jul 14, 2011
Messages
875
Well, depending on the implementation it can happen during semantic analysis.
Something like: ("a" + 1) + 2 which would give something like "cannot convert from string to integer" and then "cannot convert from null to integer", or something like that.
I dont know if that is considered bad implementation or not - Ive only made one rather simple interpreter (that would do this).
Then again, I dont have that much experience to say for sure - pretty much everything I know is from reading articles I googled, lol (so far so good, though - I really like these stuff)
 
Level 25
Joined
Feb 2, 2006
Messages
1,689
that error is not unrecoverable tho, you just skip that statement and go to the next one

Yes that is exactly what you would have to do. In JASS it should not be hard because you just can skip the line.

Of course preprocessor errors might be something else but the current state is really annoying. I have to save many many times until finally pjass is called which lists more than one error.
 
Level 19
Joined
Jul 14, 2011
Messages
875
I have to save many many times until finally pjass is called which lists more than one error.
Even then, they are still a nuisance because of the name mangling.
To be honest, sometimes JassHelper skips a lot of checks. For example, you can do://! import <you can write anything here> "TimerUtils.j" <here too> and library A uses B C D E F G (no commas).
 
Level 10
Joined
Sep 19, 2011
Messages
527
Hi pp, I finally fix override methods, check it out: https://github.com/Ruk33/vrJASS/releases/tag/v5.0.0-rc

JASS:
interface foo
  public method hi
endinterface

struct a implements foo
  public method hi
    call BJDebugMsg("Hi from A")
  endmethod
endstruct

struct b extends a
  public method hi
    call BJDebugMsg("Hi from B")
  endmethod
endstruct

local foo instance = b.allocate()
call instance.hi() // prints Hi from B
call (instance cast a).hi() // prints Hi from A
 
Last edited:
Level 10
Joined
Sep 19, 2011
Messages
527
hi there ^^, i just wanna let you know that i'm going to "implement" modules as abstract classes.

this is because modules and abstract clases share a lot in common, but the most important is that abstract classes allows you to know which methods they depend on.
 
Level 10
Joined
Sep 19, 2011
Messages
527
back again and this time with abstract classes (implemented quite poorly i have to say though, i don't have that much time u.u)

tiny note: abstract classes can be used as modules ^^

JASS:
abstract struct foo
  public method mustBeImplemented

  public static method onInit
    call BJDebugMsg("foo rulz, and i force any child class to implement my method >:3")
  end
end

struct bar extends foo
  public method mustBeImplemented
  end

  public static method onInit
    call BJDebugMsg("that foo bastard")
  end
end

prints
foo rulz, and i force any child class to implement my method >:3
that foo bastard
 
Level 10
Joined
Sep 19, 2011
Messages
527
Last edited:
Status
Not open for further replies.
Top