espruino / Espruino

The Espruino JavaScript interpreter - Official Repo
http://www.espruino.com/
Other
2.76k stars 741 forks source link

Improved Function argument handling #2266

Open gfwilliams opened 2 years ago

gfwilliams commented 2 years ago

Currently

Function arguments are stored as 'hidden' variables inside the function:

>trace(function(a,b,c) { print("Hello") }) 
#25[r0,l1] Function { 
  #26[r1,l2] Name Param "\xFFa"     undefined 
  #27[r1,l2] Name Param "\xFFb"     undefined 
  #28[r1,l2] Name Param "\xFFc"     undefined 
  #30[r1,l2] Name String [1 blocks] "\xFFcod"    #29[r1,l0] String [1 blocks] "print(\"Hello\")"  
}
// or if bound:
>trace(function(a,b,c) { print("Hello") }.bind(global,123)) 
#38[r0,l1] Function { 
  #40[r1,l2] Name Param "\xFFa" = int 123

  #39[r1,l2] Name Param "\xFFb"     undefined 
  #47[r1,l2] Name Param "\xFFc"     undefined 
  #48[r1,l2] Name String [1 blocks] "\xFFcod"    #28[r1,l0] String [1 blocks] "print(\"Hello\")"  
  #49[r1,l2] Name String [1 blocks] "\xFFths"    ROOT 
}

This isn't great from a memory usage point of view as a minified function stored in flash with 8 arguments would still use 10+ variables. It also stops us implementing default arguments nicely.

Proposed

Function arguments are stored as one text string:

>trace(function(a,b,c) { print("Hello") }) 
#25[r0,l1] Function { 
  #30[r1,l2] Name String [1 blocks] "\xFFcod"    #29[r1,l0] String [1 blocks] "print(\"Hello\")"  
  #30[r1,l2] Name String [1 blocks] "\xFFarg"    #29[r1,l0] String [1 blocks] "a,b,c"  
}
// or if bound:
>trace(function(a,b,c) { print("Hello") }.bind(global,123)) 
#38[r0,l1] Function { 
  #40[r1,l2] Name Param "a" = int 123
  #48[r1,l2] Name String [1 blocks] "\xFFcod"    #28[r1,l0] String [1 blocks] "print(\"Hello\")"  
  #30[r1,l2] Name String [1 blocks] "\xFFarg"    #29[r1,l0] String [1 blocks] "a,b,c"  
  #49[r1,l2] Name String [1 blocks] "\xFFths"    ROOT 
}
// or with default args and spread:
>trace(function(a=1,b=2,c=3,...restOfArgs) { print("Hello") }) 
#25[r0,l1] Function { 
  #30[r1,l2] Name String [1 blocks] "\xFFcod"    #29[r1,l0] String [1 blocks] "print(\"Hello\")"  
  #30[r1,l2] Name String [1 blocks] "\xFFarg"    #29[r1,l0] String [1 blocks] "a=1,b=2,c=3,...restOfArgs"  
}

This should be more memory-efficient with multiple arguments but will also allow us to do default arguments really easily, as well as the spread operator