marcobambini / gravity

Gravity Programming Language
https://gravity-lang.org
MIT License
4.28k stars 228 forks source link

Hot code reload #68

Open zilluss opened 7 years ago

zilluss commented 7 years ago

Being able to reload the code at runtime would allow for fast iteration cycles of gravity code. Upon loading a gravity script, existing classes would be replaced with the changed classes, while keeping the state of existing objects .

marcobambini commented 7 years ago

Can you please give me an example?

zilluss commented 7 years ago
//main.gravity
func main() {
  var button= ButtonWidget(100, 100)
  getWindow().addWidget(button)
}

//button.gravity
class ButtonWidget {
    var _x; var _y;    
    func init(x, y) {
        _x = x;
        _y = y;
    }  

    func onClick(event) {
        System.print("Not yet implemented")
    }
}

You change the button.gravity file and trigger a reload inside the VM host. gravity_vm_loadfile(vm, "button.gravity")

class ButtonWidget {
    ...
    func onClick(event) {
        performCalculation()
    }
}

In this case you'd still have your button at position 100/100, but clicking on it would now perform the actual calculation.

The reloading would be controlled by the VM host, so the host can implement a reload button or a filesystem watch. There should also be a flag that enables/disables hot reloading, so the user still gets useful errors in production mode (e.g. duplicate class names).

I was able to achieve something similar in Lua and Squirrel by using metamethods, which is another way to achieve hot reloading, but it's kind of a hack. Other languages offer native support for hot code reload, for example the Java HotSpot VM (although it is limited to changing the body of exising methods). Dart also offers this feature which is demonstrated here: https://www.youtube.com/watch?v=iPlPk43RbpA

marcobambini commented 7 years ago

There is already a solution for that, you can use the bind method:

class ButtonWidget {
   ...
}

var button= ButtonWidget(100, 100)

func performCalculation() { // do something here }

// bind performCalculation closure to the onClick slot
button.bind("onClick", performCalculation);
zilluss commented 7 years ago

I'm not sure if we're talking about the same thing. What I mean is to change the code of a running Gravity VM.

  1. Load and execute button.gravity and main.gravity
  2. Click on button -> System.print("Not implemented yet")
  3. Change the button.gravity file, reload button.gravity
  4. Click on button -> performCalculation is executed
marcobambini commented 7 years ago

Yes it is exactly the same thing, except that instead of your point 3 you execute the bind instruction.

zilluss commented 7 years ago

Ok, but that means you have to write your changes, write the bind instruction and then execute it to be changed, am I correct? The purpose of hot reload is that you can edit your code in-place, similar to the Swift playground.

marcobambini commented 7 years ago

Not really true, I'll soon expose the compile method that returns a closure based on source code and at that point you can easily edit code in-place and bind it to an existing object.