mirror of
https://github.com/zekexiao/pocketlang.git
synced 2025-03-04 13:15:55 +08:00
Merge pull request #251 from ThakeeNathees/method-bind
method bind implemented
This commit is contained in:
commit
0e355ed6c4
@ -1,29 +0,0 @@
|
|||||||
|
|
||||||
# math
|
|
||||||
|
|
||||||
TODO: this page is incomplete.
|
|
||||||
|
|
||||||
#### math.floor
|
|
||||||
```ruby
|
|
||||||
floor(value:num) -> num
|
|
||||||
```
|
|
||||||
|
|
||||||
#### math.ceil
|
|
||||||
```ruby
|
|
||||||
ceil(value:num) -> num
|
|
||||||
```
|
|
||||||
|
|
||||||
#### math.pow
|
|
||||||
```ruby
|
|
||||||
pow(a:num, b:num) -> num
|
|
||||||
```
|
|
||||||
|
|
||||||
#### math.sqrt
|
|
||||||
```ruby
|
|
||||||
sqrt(value:num) -> num
|
|
||||||
```
|
|
||||||
|
|
||||||
#### math.abs
|
|
||||||
```ruby
|
|
||||||
abs(value:num) -> num
|
|
||||||
```
|
|
@ -1,23 +0,0 @@
|
|||||||
# path
|
|
||||||
|
|
||||||
TODO: this page is incomplete.
|
|
||||||
|
|
||||||
#### path.getcwd
|
|
||||||
```ruby
|
|
||||||
getcwd() -> str
|
|
||||||
```
|
|
||||||
|
|
||||||
#### path.abspath
|
|
||||||
```ruby
|
|
||||||
abspath(path:str) -> str
|
|
||||||
```
|
|
||||||
|
|
||||||
#### path.relpath
|
|
||||||
```ruby
|
|
||||||
relpath(path:str) -> str
|
|
||||||
```
|
|
||||||
|
|
||||||
#### path.join
|
|
||||||
```ruby
|
|
||||||
join(...path:str) -> str
|
|
||||||
```
|
|
99
docs/Reference/io.md
Normal file
99
docs/Reference/io.md
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
# io
|
||||||
|
|
||||||
|
### write
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
io.write(stream:Var, bytes:String) -> Null
|
||||||
|
```
|
||||||
|
|
||||||
|
Warning: the function is subjected to be changed anytime soon.
|
||||||
|
Write [bytes] string to the stream. stream should be any of io.stdin, io.stdout, io.stderr.
|
||||||
|
|
||||||
|
### flush
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
io.flush() -> Null
|
||||||
|
```
|
||||||
|
|
||||||
|
Warning: the function is subjected to be changed anytime soon.
|
||||||
|
Flush stdout buffer.
|
||||||
|
|
||||||
|
### getc
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
io.getc() -> String
|
||||||
|
```
|
||||||
|
|
||||||
|
Read a single character from stdin and return it.
|
||||||
|
|
||||||
|
## File
|
||||||
|
A simple file type.
|
||||||
|
|
||||||
|
### open
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
io.File.open(path:String, mode:String) -> Null
|
||||||
|
```
|
||||||
|
|
||||||
|
Opens a file at the [path] with the [mode]. Path should be either absolute or relative to the current working directory. and [mode] can be'r', 'w', 'a' in combination with 'b' (binary) and/or '+' (extended).
|
||||||
|
```
|
||||||
|
mode | If already exists | If does not exist |
|
||||||
|
-----+-------------------+-------------------|
|
||||||
|
'r' | read from start | failure to open |
|
||||||
|
'w' | destroy contents | create new |
|
||||||
|
'a' | write to end | create new |
|
||||||
|
'r+' | read from start | error |
|
||||||
|
'w+' | destroy contents | create new |
|
||||||
|
'a+' | write to end | create new |
|
||||||
|
```
|
||||||
|
|
||||||
|
### read
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
io.File.read(count:Number) -> String
|
||||||
|
```
|
||||||
|
|
||||||
|
Reads [count] number of bytes from the file and return it as String.If the count is -1 it'll read till the end of file and return it.
|
||||||
|
|
||||||
|
### write
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
io.File.write(data:String) -> Null
|
||||||
|
```
|
||||||
|
|
||||||
|
Write the [data] to the file. Since pocketlang string support any validbyte value in it's string, binary data can also be written with strings.
|
||||||
|
|
||||||
|
### getline
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
io.File.getline() -> String
|
||||||
|
```
|
||||||
|
|
||||||
|
Reads a line from the file and return it as string. This function can only be used for files that are opened with text mode.
|
||||||
|
|
||||||
|
### close
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
io.File.close()
|
||||||
|
```
|
||||||
|
|
||||||
|
Closes the opend file.
|
||||||
|
|
||||||
|
### seek
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
io.File.seek(offset:Number, whence:Number) -> Null
|
||||||
|
```
|
||||||
|
|
||||||
|
Move the file read/write offset. where [offset] is the offset from [whence] which should be any of the bellow three.
|
||||||
|
0: Begining of the file.
|
||||||
|
1: Current position.
|
||||||
|
2: End of the file.
|
||||||
|
|
||||||
|
### tell
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
io.File.tell() -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the read/write position of the file.
|
17
docs/Reference/json.md
Normal file
17
docs/Reference/json.md
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# json
|
||||||
|
|
||||||
|
### parse
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
json.parse(json_str:String) -> Var
|
||||||
|
```
|
||||||
|
|
||||||
|
Parse a json string into pocket lang object.
|
||||||
|
|
||||||
|
### print
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
json.print(value:Var, pretty:Bool=false)
|
||||||
|
```
|
||||||
|
|
||||||
|
Render a pocketlang value into text. Takes an optional argument pretty, if true it'll pretty print the output.
|
42
docs/Reference/lang.md
Normal file
42
docs/Reference/lang.md
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# lang
|
||||||
|
|
||||||
|
### gc
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
lang.gc() -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Trigger garbage collection and return the amount of bytes cleaned.
|
||||||
|
|
||||||
|
### disas
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
lang.disas(fn:Closure) -> String
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the disassembled opcode of the function [fn].
|
||||||
|
|
||||||
|
### backtrace
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
lang.backtrace() -> String
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the backtrace as a string, each line is formated as '<function>;<file>;<line>
|
||||||
|
'.
|
||||||
|
|
||||||
|
### modules
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
lang.modules() -> List
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the list of all registered modules.
|
||||||
|
|
||||||
|
### debug_break
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
lang.debug_break() -> Null
|
||||||
|
```
|
||||||
|
|
||||||
|
A debug function for development (will be removed).
|
145
docs/Reference/math.md
Normal file
145
docs/Reference/math.md
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
# math
|
||||||
|
|
||||||
|
### floor
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
math.floor(value:Numberber) -> Numberber
|
||||||
|
```
|
||||||
|
|
||||||
|
Return the floor value.
|
||||||
|
|
||||||
|
### ceil
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
math.ceil(value:Number) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the ceiling value.
|
||||||
|
|
||||||
|
### pow
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
math.pow(a:Number, b:Number) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the power 'b' of 'a' similler to a**b.
|
||||||
|
|
||||||
|
### sqrt
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
math.sqrt(value:Number) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the square root of the value
|
||||||
|
|
||||||
|
### abs
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
math.abs(value:Number) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the absolute value.
|
||||||
|
|
||||||
|
### sign
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
math.sign(value:Number) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
return the sign of the which is one of (+1, 0, -1).
|
||||||
|
|
||||||
|
### sin
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
math.sin(rad:Number) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Return the sine value of the argument [rad] which is an angle expressed in radians.
|
||||||
|
|
||||||
|
### cos
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
math.cos(rad:Number) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Return the cosine value of the argument [rad] which is an angle expressed in radians.
|
||||||
|
|
||||||
|
### tan
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
math.tan(rad:Number) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Return the tangent value of the argument [rad] which is an angle expressed in radians.
|
||||||
|
|
||||||
|
### sinh
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
math.sinh(val:Number) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Return the hyperbolic sine value of the argument [val].
|
||||||
|
|
||||||
|
### cosh
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
math.cosh(val:Number) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Return the hyperbolic cosine value of the argument [val].
|
||||||
|
|
||||||
|
### tanh
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
math.tanh(val:Number) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Return the hyperbolic tangent value of the argument [val].
|
||||||
|
|
||||||
|
### asin
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
math.asin(num:Number) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Return the arcsine value of the argument [num] which is an angle expressed in radians.
|
||||||
|
|
||||||
|
### acos
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
math.acos(num:Number) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Return the arc cosine value of the argument [num] which is an angle expressed in radians.
|
||||||
|
|
||||||
|
### atan
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
math.atan(num:Number) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Return the arc tangent value of the argument [num] which is an angle expressed in radians.
|
||||||
|
|
||||||
|
### log10
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
math.log10(value:Number) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Return the logarithm to base 10 of argument [value]
|
||||||
|
|
||||||
|
### round
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
math.round(value:Number) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Round to nearest integer, away from zero and return the number.
|
||||||
|
|
||||||
|
### rand
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
math.rand() -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Return a random runber in the range of 0..0x7fff.
|
81
docs/Reference/os.md
Normal file
81
docs/Reference/os.md
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
# os
|
||||||
|
|
||||||
|
### getcwd
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
os.getcwd() -> String
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the current working directory
|
||||||
|
|
||||||
|
### chdir
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
os.chdir(path:String)
|
||||||
|
```
|
||||||
|
|
||||||
|
Change the current working directory
|
||||||
|
|
||||||
|
### mkdir
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
os.mkdir(path:String)
|
||||||
|
```
|
||||||
|
|
||||||
|
Creates a directory at the path. The path should be valid.
|
||||||
|
|
||||||
|
### rmdir
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
os.rmdir(path:String)
|
||||||
|
```
|
||||||
|
|
||||||
|
Removes an empty directory at the path.
|
||||||
|
|
||||||
|
### unlink
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
os.rmdir(path:String)
|
||||||
|
```
|
||||||
|
|
||||||
|
Removes a file at the path.
|
||||||
|
|
||||||
|
### moditime
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
os.moditime(path:String) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the modified timestamp of the file.
|
||||||
|
|
||||||
|
### filesize
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
os.filesize(path:String) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the file size in bytes.
|
||||||
|
|
||||||
|
### system
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
os.system(cmd:String) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Execute the command in a subprocess, Returns the exit code of the child process.
|
||||||
|
|
||||||
|
### getenv
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
os.getenv(name:String) -> String
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the environment variable as String if it exists otherwise it'll return null.
|
||||||
|
|
||||||
|
### exepath
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
os.exepath() -> String
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the path of the pocket interpreter executable.
|
105
docs/Reference/path.md
Normal file
105
docs/Reference/path.md
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
# path
|
||||||
|
|
||||||
|
### getcwd
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
path.getcwd() -> String
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the current working directory.
|
||||||
|
|
||||||
|
### abspath
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
path.abspath(path:String) -> String
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the absolute path of the [path].
|
||||||
|
|
||||||
|
### relpath
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
path.relpath(path:String, from:String) -> String
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the relative path of the [path] argument from the [from] directory.
|
||||||
|
|
||||||
|
### join
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
path.join(...) -> String
|
||||||
|
```
|
||||||
|
|
||||||
|
Joins path with path seperator and return it. The maximum count of paths which can be joined for a call is MAX_JOIN_PATHS.
|
||||||
|
|
||||||
|
### normpath
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
path.normpath(path:String) -> String
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the normalized path of the [path].
|
||||||
|
|
||||||
|
### basename
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
path.basename(path:String) -> String
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the final component for the path
|
||||||
|
|
||||||
|
### dirname
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
path.dirname(path:String) -> String
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the directory of the path.
|
||||||
|
|
||||||
|
### isabspath
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
path.isabspath(path:String) -> Bool
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns true if the path is absolute otherwise false.
|
||||||
|
|
||||||
|
### getext
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
path.getext(path:String) -> String
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the file extension of the path.
|
||||||
|
|
||||||
|
### exists
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
path.exists(path:String) -> String
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns true if the file exists.
|
||||||
|
|
||||||
|
### isfile
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
path.isfile(path:String) -> Bool
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns true if the path is a file.
|
||||||
|
|
||||||
|
### isdir
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
path.isdir(path:String) -> Bool
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns true if the path is a directory.
|
||||||
|
|
||||||
|
### listdir
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
path.listdir(path:String='.') -> List
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns all the entries in the directory at the [path].
|
76
docs/Reference/term.md
Normal file
76
docs/Reference/term.md
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
# term
|
||||||
|
|
||||||
|
### init
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
term.init(capture_events:Bool) -> Null
|
||||||
|
```
|
||||||
|
|
||||||
|
Initialize terminal with raw mode for tui applications, set [capture_events] true to enable event handling.
|
||||||
|
|
||||||
|
### cleanup
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
term.cleanup() -> Null
|
||||||
|
```
|
||||||
|
|
||||||
|
Cleanup and resotre the last terminal state.
|
||||||
|
|
||||||
|
### isatty
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
term.isatty() -> Bool
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns true if both stdin and stdout are tty.
|
||||||
|
|
||||||
|
### new_screen_buffer
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
term.new_screen_buffer() -> Null
|
||||||
|
```
|
||||||
|
|
||||||
|
Switch to an alternative screen buffer.
|
||||||
|
|
||||||
|
### restore_screen_buffer
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
term.restore_screen_buffer() -> Null
|
||||||
|
```
|
||||||
|
|
||||||
|
Restore the alternative buffer which was created with term.new_screen_buffer()
|
||||||
|
|
||||||
|
### getsize
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
term.getsize() -> types.Vector
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the screen size.
|
||||||
|
|
||||||
|
### getposition
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
term.getposition() -> types.Vector
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the cursor position in the screen on a zero based coordinate.
|
||||||
|
|
||||||
|
### read_event
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
term.read_event(event:term.Event) -> Bool
|
||||||
|
```
|
||||||
|
|
||||||
|
Read an event and update the argument [event] and return true.If no event was read it'll return false.
|
||||||
|
|
||||||
|
## Event
|
||||||
|
The terminal event type, that'll be used at term.read_event function to fetch events.
|
||||||
|
|
||||||
|
### binary_mode
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
term.binary_mode() -> Null
|
||||||
|
```
|
||||||
|
|
||||||
|
On windows it'll set stdout to binary mode, on other platforms this function won't make make any difference.
|
25
docs/Reference/time.md
Normal file
25
docs/Reference/time.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# time
|
||||||
|
|
||||||
|
### epoch
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
time() -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the number of seconds since the Epoch, 1970-01-01 00:00:00 +0000 (UTC).
|
||||||
|
|
||||||
|
### sleep
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
sleep(t:num) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Sleep for [t] milliseconds.
|
||||||
|
|
||||||
|
### clock
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
clock() -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the number of clocks passed divied by CLOCKS_PER_SEC.
|
95
docs/Reference/types.md
Normal file
95
docs/Reference/types.md
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
# types
|
||||||
|
|
||||||
|
### hashable
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
types.hashable(value:Var) -> Bool
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns true if the [value] is hashable.
|
||||||
|
|
||||||
|
### hash
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
types.hash(value:Var) -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the hash of the [value]
|
||||||
|
|
||||||
|
## ByteBuffer
|
||||||
|
A simple dynamically allocated byte buffer type. This can be used for constructing larger strings without allocating and adding smaller intermeidate strings.
|
||||||
|
|
||||||
|
### []
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
types.ByteBuffer.[](index:Number)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### []=
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
types.ByteBuffer.[]=(index:Number, value:Number)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### reserve
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
types.ByteBuffer.reserve(count:Number) -> Null
|
||||||
|
```
|
||||||
|
|
||||||
|
Reserve [count] number of bytes internally. This is use full if the final size of the buffer is known beforehand to avoid reduce the number of re-allocations.
|
||||||
|
|
||||||
|
### fill
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
types.ByteBuffer.fill(value:Number) -> Null
|
||||||
|
```
|
||||||
|
|
||||||
|
Fill the buffer with the given byte value. Note that the value must be in between 0 and 0xff inclusive.
|
||||||
|
|
||||||
|
### clear
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
types.ByteBuffer.clear() -> Null
|
||||||
|
```
|
||||||
|
|
||||||
|
Clear the buffer values.
|
||||||
|
|
||||||
|
### write
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
types.ByteBuffer.write(data:Number|String) -> Null
|
||||||
|
```
|
||||||
|
|
||||||
|
Writes the data to the buffer. If the [data] is a number that should be in between 0 and 0xff inclusively. If the [data] is a string all the bytes of the string will be written to the buffer.
|
||||||
|
|
||||||
|
### string
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
types.ByteBuffer.string() -> String
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the buffered values as String.
|
||||||
|
|
||||||
|
### count
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
types.ByteBuffer.count() -> Number
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the number of bytes that have written to the buffer.
|
||||||
|
|
||||||
|
## Vector
|
||||||
|
A simple vector type contains x, y, and z components.
|
||||||
|
|
||||||
|
### _repr
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
types.Vector._repr()
|
||||||
|
```
|
||||||
|
|
||||||
|
|
@ -1,8 +1,14 @@
|
|||||||
|
|
||||||
* Getting Started
|
* Getting Started
|
||||||
* [Home](/)
|
* [Home](/)
|
||||||
* [Language Manual](/GettingStarted/LanguageManual.md)
|
* [Language Manual](/GettingStarted/LanguageManual.md)
|
||||||
|
|
||||||
* Library Reference
|
* Library Reference
|
||||||
* [math](/Reference/Math.md)
|
* [io](/Reference/io.md)
|
||||||
* [path](/Reference/Path.md)
|
* [json](/Reference/json.md)
|
||||||
|
* [time](/Reference/time.md)
|
||||||
|
* [lang](/Reference/lang.md)
|
||||||
|
* [path](/Reference/path.md)
|
||||||
|
* [os](/Reference/os.md)
|
||||||
|
* [term](/Reference/term.md)
|
||||||
|
* [types](/Reference/types.md)
|
||||||
|
* [math](/Reference/math.md)
|
||||||
|
93
scripts/docs_gen.pk
Normal file
93
scripts/docs_gen.pk
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
#!pocket
|
||||||
|
## Copyright (c) 2020-2021 Thakee Nathees
|
||||||
|
## Copyright (c) 2021-2022 Pocketlang Contributors
|
||||||
|
## Distributed Under The MIT License
|
||||||
|
|
||||||
|
import lang
|
||||||
|
from path import dirname, join, normpath
|
||||||
|
|
||||||
|
ROOT_PATH = normpath(join(dirname(__file__), '..'))
|
||||||
|
|
||||||
|
REFERENCE_DIR = join(ROOT_PATH, 'docs/Reference/')
|
||||||
|
SIDEBAR_FILE = join(ROOT_PATH, 'docs/_sidebar.md')
|
||||||
|
|
||||||
|
sidebar = "\
|
||||||
|
* Getting Started
|
||||||
|
* [Home](/)
|
||||||
|
* [Language Manual](/GettingStarted/LanguageManual.md)
|
||||||
|
|
||||||
|
* Library Reference
|
||||||
|
"
|
||||||
|
|
||||||
|
def main()
|
||||||
|
for module in lang.modules()
|
||||||
|
## Dummy module is for testing internals and will be
|
||||||
|
##removed soon so skip it.
|
||||||
|
if module._name == 'dummy'
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
f = open(join(REFERENCE_DIR, module._name + '.md'), 'w')
|
||||||
|
gen_module_docs(f, module)
|
||||||
|
f.close()
|
||||||
|
end
|
||||||
|
|
||||||
|
f = open(SIDEBAR_FILE, 'w')
|
||||||
|
f.write(sidebar)
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
## Write the [module]'s documentation content to the file [f].
|
||||||
|
def gen_module_docs(f, module)
|
||||||
|
name = module._name
|
||||||
|
sidebar += ' * [$name](/Reference/$name.md)\n'
|
||||||
|
f.write('# $name\n')
|
||||||
|
for global in module.globals()
|
||||||
|
|
||||||
|
{ ## Map as switch statement alternative.
|
||||||
|
Null: fn end,
|
||||||
|
Number: fn end,
|
||||||
|
String: fn end,
|
||||||
|
|
||||||
|
Closure : fn
|
||||||
|
write_fn_doc(f, global)
|
||||||
|
end,
|
||||||
|
|
||||||
|
Class: fn
|
||||||
|
write_cls_doc(f, global)
|
||||||
|
end,
|
||||||
|
|
||||||
|
} [global._class]()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
## Write the function's documentation to the file [f].
|
||||||
|
def write_fn_doc(f, func)
|
||||||
|
f.write('\n')
|
||||||
|
f.write('### ${func.name}\n')
|
||||||
|
f.write('\n')
|
||||||
|
i = func._docs.find('\n\n')
|
||||||
|
symbol = func._docs[0..i-1]
|
||||||
|
desc = func._docs[i+1..-1]
|
||||||
|
f.write("```ruby\n$symbol\n```\n")
|
||||||
|
f.write(desc)
|
||||||
|
f.write('\n')
|
||||||
|
end
|
||||||
|
|
||||||
|
## Write the class's documentation to the file [f].
|
||||||
|
def write_cls_doc(f, cls)
|
||||||
|
f.write('\n')
|
||||||
|
f.write('## ${cls.name}\n')
|
||||||
|
f.write('${cls._docs}\n')
|
||||||
|
for method in cls.methods()
|
||||||
|
if method.name == '_init'
|
||||||
|
continue ## Constructor.
|
||||||
|
end
|
||||||
|
write_fn_doc(f, method)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if _name == "@main"
|
||||||
|
main()
|
||||||
|
end
|
182
src/core/core.c
182
src/core/core.c
@ -145,9 +145,11 @@ void initializeModule(PKVM* vm, Module* module, bool is_main) {
|
|||||||
String *path = module->path, *name = NULL;
|
String *path = module->path, *name = NULL;
|
||||||
|
|
||||||
if (is_main) {
|
if (is_main) {
|
||||||
// TODO: consider static string "__main__" stored in PKVM. to reduce
|
// TODO: consider static string "@main" stored in PKVM. to reduce
|
||||||
// allocations everytime here.
|
// allocations everytime here.
|
||||||
name = newString(vm, "__main__");
|
ASSERT(module->name == NULL, OOPS);
|
||||||
|
name = newString(vm, "@main");
|
||||||
|
module->name = name;
|
||||||
vmPushTempRef(vm, &name->_super); // _main.
|
vmPushTempRef(vm, &name->_super); // _main.
|
||||||
} else {
|
} else {
|
||||||
ASSERT(module->name != NULL, OOPS);
|
ASSERT(module->name != NULL, OOPS);
|
||||||
@ -163,7 +165,7 @@ void initializeModule(PKVM* vm, Module* module, bool is_main) {
|
|||||||
moduleSetGlobal(vm, module, "__file__", 8, VAR_OBJ(path));
|
moduleSetGlobal(vm, module, "__file__", 8, VAR_OBJ(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
moduleSetGlobal(vm, module, "__name__", 8, VAR_OBJ(name));
|
moduleSetGlobal(vm, module, "_name", 5, VAR_OBJ(name));
|
||||||
|
|
||||||
if (is_main) vmPopTempRef(vm); // _main.
|
if (is_main) vmPopTempRef(vm); // _main.
|
||||||
}
|
}
|
||||||
@ -272,7 +274,7 @@ static void _collectMethods(PKVM* vm, List* list, Class* cls) {
|
|||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
DEF(coreHelp,
|
DEF(coreHelp,
|
||||||
"help([value:Closure|Class]) -> Null",
|
"help([value:Closure|MethodBind|Class]) -> Null",
|
||||||
"It'll print the docstring the object and return.") {
|
"It'll print the docstring the object and return.") {
|
||||||
|
|
||||||
int argc = ARGC;
|
int argc = ARGC;
|
||||||
@ -305,6 +307,18 @@ DEF(coreHelp,
|
|||||||
vm->config.stdout_write(vm, closure->fn->name);
|
vm->config.stdout_write(vm, closure->fn->name);
|
||||||
vm->config.stdout_write(vm, "()' doesn't have a docstring.\n");
|
vm->config.stdout_write(vm, "()' doesn't have a docstring.\n");
|
||||||
}
|
}
|
||||||
|
} else if (IS_OBJ_TYPE(value, OBJ_METHOD_BIND)) {
|
||||||
|
MethodBind* mb = (MethodBind*) AS_OBJ(value);
|
||||||
|
// If there ins't an io function callback, we're done.
|
||||||
|
|
||||||
|
if (mb->method->fn->docstring != NULL) {
|
||||||
|
vm->config.stdout_write(vm, mb->method->fn->docstring);
|
||||||
|
vm->config.stdout_write(vm, "\n\n");
|
||||||
|
} else {
|
||||||
|
vm->config.stdout_write(vm, "method '");
|
||||||
|
vm->config.stdout_write(vm, mb->method->fn->name);
|
||||||
|
vm->config.stdout_write(vm, "()' doesn't have a docstring.\n");
|
||||||
|
}
|
||||||
} else if (IS_OBJ_TYPE(value, OBJ_CLASS)) {
|
} else if (IS_OBJ_TYPE(value, OBJ_CLASS)) {
|
||||||
Class* cls = (Class*) AS_OBJ(value);
|
Class* cls = (Class*) AS_OBJ(value);
|
||||||
if (cls->docstring != NULL) {
|
if (cls->docstring != NULL) {
|
||||||
@ -316,7 +330,8 @@ DEF(coreHelp,
|
|||||||
vm->config.stdout_write(vm, "' doesn't have a docstring.\n");
|
vm->config.stdout_write(vm, "' doesn't have a docstring.\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
RET_ERR(newString(vm, "Expected a closure or class to get help."));
|
RET_ERR(newString(vm, "Expected a Closure, MethodBind or "
|
||||||
|
"Class to get help."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,7 +420,7 @@ DEF(coreAssert,
|
|||||||
String* msg = NULL;
|
String* msg = NULL;
|
||||||
|
|
||||||
if (argc == 2) {
|
if (argc == 2) {
|
||||||
if (AS_OBJ(ARG(2))->type != OBJ_STRING) {
|
if (!IS_OBJ_TYPE(ARG(2), OBJ_STRING)) {
|
||||||
msg = varToString(vm, ARG(2), false);
|
msg = varToString(vm, ARG(2), false);
|
||||||
if (msg == NULL) return; //< Error at _to_string override.
|
if (msg == NULL) return; //< Error at _to_string override.
|
||||||
|
|
||||||
@ -828,7 +843,14 @@ DEF(stdLangModules,
|
|||||||
vmPushTempRef(vm, &list->_super); // list.
|
vmPushTempRef(vm, &list->_super); // list.
|
||||||
for (uint32_t i = 0; i < vm->modules->capacity; i++) {
|
for (uint32_t i = 0; i < vm->modules->capacity; i++) {
|
||||||
if (!IS_UNDEF(vm->modules->entries[i].key)) {
|
if (!IS_UNDEF(vm->modules->entries[i].key)) {
|
||||||
listAppend(vm, list, vm->modules->entries[i].value);
|
Var entry = vm->modules->entries[i].value;
|
||||||
|
ASSERT(IS_OBJ_TYPE(entry, OBJ_MODULE), OOPS);
|
||||||
|
Module* module = (Module*) AS_OBJ(entry);
|
||||||
|
ASSERT(module->name != NULL, OOPS);
|
||||||
|
if (module->name->data[0] == SPECIAL_NAME_CHAR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
listAppend(vm, list, entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vmPopTempRef(vm); // list.
|
vmPopTempRef(vm); // list.
|
||||||
@ -1268,6 +1290,78 @@ DEF(_mapPop,
|
|||||||
RET(value);
|
RET(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEF(_methodBindBind,
|
||||||
|
"MethodBind.bind(instance:Var) -> MethodBind",
|
||||||
|
"Bind the method to the instance and the method bind will be returned. The "
|
||||||
|
"method should be a valid method of the instance. ie. the instance's "
|
||||||
|
"interitance tree should contain the method.") {
|
||||||
|
|
||||||
|
MethodBind* self = (MethodBind*) AS_OBJ(SELF);
|
||||||
|
|
||||||
|
// We can only bind the method if the instance has that method.
|
||||||
|
String* method_name = newString(vm, self->method->fn->name);
|
||||||
|
vmPushTempRef(vm, &method_name->_super); // method_name.
|
||||||
|
|
||||||
|
Var instance = ARG(1);
|
||||||
|
|
||||||
|
Closure* method;
|
||||||
|
if (!hasMethod(vm, instance, method_name, &method)
|
||||||
|
|| method != self->method) {
|
||||||
|
VM_SET_ERROR(vm, newString(vm, "Cannot bind method, instance and method "
|
||||||
|
"types miss-match."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->instance = instance;
|
||||||
|
vmPopTempRef(vm); // method_name.
|
||||||
|
|
||||||
|
RET(SELF);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEF(_classMethods,
|
||||||
|
"Class.methods() -> List",
|
||||||
|
"Returns a list of unbound MethodBind of the class.") {
|
||||||
|
|
||||||
|
Class* self = (Class*) AS_OBJ(SELF);
|
||||||
|
|
||||||
|
List* list = newList(vm, self->methods.count);
|
||||||
|
vmPushTempRef(vm, &list->_super); // list.
|
||||||
|
for (int i = 0; i < (int) self->methods.count; i++) {
|
||||||
|
Closure* method = self->methods.data[i];
|
||||||
|
ASSERT(method->fn->name, OOPS);
|
||||||
|
if (method->fn->name[0] == SPECIAL_NAME_CHAR) continue;
|
||||||
|
MethodBind* mb = newMethodBind(vm, method);
|
||||||
|
vmPushTempRef(vm, &mb->_super); // mb.
|
||||||
|
listAppend(vm, list, VAR_OBJ(mb));
|
||||||
|
vmPopTempRef(vm); // mb.
|
||||||
|
}
|
||||||
|
vmPopTempRef(vm); // list.
|
||||||
|
|
||||||
|
RET(VAR_OBJ(list));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DEF(_moduleGlobals,
|
||||||
|
"Module.globals() -> List",
|
||||||
|
"Returns a list of all the globals in the module. Since classes and "
|
||||||
|
"functinos are also globals to a module it'll contain them too.") {
|
||||||
|
|
||||||
|
Module* self = (Module*) AS_OBJ(SELF);
|
||||||
|
|
||||||
|
List* list = newList(vm, self->globals.count);
|
||||||
|
vmPushTempRef(vm, &list->_super); // list.
|
||||||
|
for (int i = 0; i < (int) self->globals.count; i++) {
|
||||||
|
if (moduleGetStringAt(self,
|
||||||
|
self->global_names.data[i])->data[0] == SPECIAL_NAME_CHAR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
listAppend(vm, list, self->globals.data[i]);
|
||||||
|
}
|
||||||
|
vmPopTempRef(vm); // list.
|
||||||
|
|
||||||
|
RET(VAR_OBJ(list));
|
||||||
|
}
|
||||||
|
|
||||||
DEF(_fiberRun,
|
DEF(_fiberRun,
|
||||||
"Fiber.run(...) -> Var",
|
"Fiber.run(...) -> Var",
|
||||||
"Runs the fiber's function with the provided arguments and returns it's "
|
"Runs the fiber's function with the provided arguments and returns it's "
|
||||||
@ -1383,6 +1477,12 @@ static void initializePrimitiveClasses(PKVM* vm) {
|
|||||||
ADD_METHOD(PK_MAP, "has", _mapHas, 1);
|
ADD_METHOD(PK_MAP, "has", _mapHas, 1);
|
||||||
ADD_METHOD(PK_MAP, "pop", _mapPop, 1);
|
ADD_METHOD(PK_MAP, "pop", _mapPop, 1);
|
||||||
|
|
||||||
|
ADD_METHOD(PK_METHOD_BIND, "bind", _methodBindBind, 1);
|
||||||
|
|
||||||
|
ADD_METHOD(PK_CLASS, "methods", _classMethods, 0);
|
||||||
|
|
||||||
|
ADD_METHOD(PK_MODULE, "globals", _moduleGlobals, 0);
|
||||||
|
|
||||||
ADD_METHOD(PK_FIBER, "run", _fiberRun, -1);
|
ADD_METHOD(PK_FIBER, "run", _fiberRun, -1);
|
||||||
ADD_METHOD(PK_FIBER, "resume", _fiberResume, -1);
|
ADD_METHOD(PK_FIBER, "resume", _fiberResume, -1);
|
||||||
|
|
||||||
@ -1867,6 +1967,10 @@ Var varGetAttrib(PKVM* vm, Var on, String* attrib) {
|
|||||||
VM_SET_ERROR(vm, stringFormat(vm, "'$' object has no attribute named '$'.", \
|
VM_SET_ERROR(vm, stringFormat(vm, "'$' object has no attribute named '$'.", \
|
||||||
varTypeName(on), attrib->data))
|
varTypeName(on), attrib->data))
|
||||||
|
|
||||||
|
if (attrib->hash == CHECK_HASH("_class", 0xa2d93eae)) {
|
||||||
|
return VAR_OBJ(getClass(vm, on));
|
||||||
|
}
|
||||||
|
|
||||||
if (!IS_OBJ(on)) {
|
if (!IS_OBJ(on)) {
|
||||||
ERR_NO_ATTRIB(vm, on, attrib);
|
ERR_NO_ATTRIB(vm, on, attrib);
|
||||||
return VAR_NULL;
|
return VAR_NULL;
|
||||||
@ -1933,6 +2037,9 @@ Var varGetAttrib(PKVM* vm, Var on, String* attrib) {
|
|||||||
Closure* closure = (Closure*)obj;
|
Closure* closure = (Closure*)obj;
|
||||||
switch (attrib->hash) {
|
switch (attrib->hash) {
|
||||||
|
|
||||||
|
case CHECK_HASH("name", 0x8d39bde6):
|
||||||
|
return VAR_OBJ(newString(vm, closure->fn->name));
|
||||||
|
|
||||||
case CHECK_HASH("_docs", 0x8fb536a9):
|
case CHECK_HASH("_docs", 0x8fb536a9):
|
||||||
if (closure->fn->docstring) {
|
if (closure->fn->docstring) {
|
||||||
return VAR_OBJ(newString(vm, closure->fn->docstring));
|
return VAR_OBJ(newString(vm, closure->fn->docstring));
|
||||||
@ -1943,11 +2050,30 @@ Var varGetAttrib(PKVM* vm, Var on, String* attrib) {
|
|||||||
case CHECK_HASH("arity", 0x3e96bd7a):
|
case CHECK_HASH("arity", 0x3e96bd7a):
|
||||||
return VAR_NUM((double)(closure->fn->arity));
|
return VAR_NUM((double)(closure->fn->arity));
|
||||||
|
|
||||||
case CHECK_HASH("name", 0x8d39bde6):
|
|
||||||
return VAR_OBJ(newString(vm, closure->fn->name));
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case OBJ_METHOD_BIND: {
|
||||||
|
MethodBind* mb = (MethodBind*) obj;
|
||||||
|
|
||||||
|
switch (attrib->hash) {
|
||||||
|
case CHECK_HASH("_docs", 0x8fb536a9):
|
||||||
|
if (mb->method->fn->docstring) {
|
||||||
|
return VAR_OBJ(newString(vm, mb->method->fn->docstring));
|
||||||
|
} else {
|
||||||
|
return VAR_OBJ(newString(vm, ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
case CHECK_HASH("name", 0x8d39bde6):
|
||||||
|
return VAR_OBJ(newString(vm, mb->method->fn->name));
|
||||||
|
|
||||||
|
case CHECK_HASH("instance", 0xb86d992):
|
||||||
|
if (IS_UNDEF(mb->instance)) return VAR_NULL;
|
||||||
|
return mb->instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
} break;
|
||||||
|
|
||||||
case OBJ_UPVALUE:
|
case OBJ_UPVALUE:
|
||||||
UNREACHABLE(); // Upvalues aren't first class objects.
|
UNREACHABLE(); // Upvalues aren't first class objects.
|
||||||
break;
|
break;
|
||||||
@ -1966,11 +2092,32 @@ Var varGetAttrib(PKVM* vm, Var on, String* attrib) {
|
|||||||
|
|
||||||
case OBJ_CLASS: {
|
case OBJ_CLASS: {
|
||||||
Class* cls = (Class*) obj;
|
Class* cls = (Class*) obj;
|
||||||
if (attrib->hash == CHECK_HASH("_docs", 0x8fb536a9)) {
|
|
||||||
if (cls->docstring) {
|
switch (attrib->hash) {
|
||||||
return VAR_OBJ(newString(vm, cls->docstring));
|
case CHECK_HASH("_docs", 0x8fb536a9):
|
||||||
} else {
|
if (cls->docstring) {
|
||||||
return VAR_OBJ(newString(vm, ""));
|
return VAR_OBJ(newString(vm, cls->docstring));
|
||||||
|
} else {
|
||||||
|
return VAR_OBJ(newString(vm, ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
case CHECK_HASH("name", 0x8d39bde6):
|
||||||
|
return VAR_OBJ(newString(vm, cls->name->data));
|
||||||
|
|
||||||
|
case CHECK_HASH("parent", 0xeacdfcfd):
|
||||||
|
if (cls->super_class != NULL) {
|
||||||
|
return VAR_OBJ(cls->super_class);
|
||||||
|
} else {
|
||||||
|
return VAR_NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)cls->methods.count; i++) {
|
||||||
|
Closure* method_ = cls->methods.data[i];
|
||||||
|
ASSERT(method_->fn->is_method, OOPS);
|
||||||
|
const char* method_name = method_->fn->name;
|
||||||
|
if (IS_CSTR_EQ(attrib, method_name, strlen(method_name))) {
|
||||||
|
return VAR_OBJ(newMethodBind(vm, method_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1999,6 +2146,13 @@ Var varGetAttrib(PKVM* vm, Var on, String* attrib) {
|
|||||||
value = mapGet(inst->attribs, VAR_OBJ(attrib));
|
value = mapGet(inst->attribs, VAR_OBJ(attrib));
|
||||||
if (!IS_UNDEF(value)) return value;
|
if (!IS_UNDEF(value)) return value;
|
||||||
|
|
||||||
|
Closure* method;
|
||||||
|
if (hasMethod(vm, on, attrib, &method)) {
|
||||||
|
MethodBind* mb = newMethodBind(vm, method);
|
||||||
|
mb->instance = on;
|
||||||
|
return VAR_OBJ(mb);
|
||||||
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,6 +189,15 @@ static void popMarkedObjectsInternal(Object* obj, PKVM* vm) {
|
|||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case OBJ_METHOD_BIND:
|
||||||
|
{
|
||||||
|
MethodBind* mb = (MethodBind*) obj;
|
||||||
|
markObject(vm, &mb->method->_super);
|
||||||
|
markValue(vm, mb->instance);
|
||||||
|
|
||||||
|
vm->bytes_allocated += sizeof(MethodBind);
|
||||||
|
} break;
|
||||||
|
|
||||||
case OBJ_UPVALUE:
|
case OBJ_UPVALUE:
|
||||||
{
|
{
|
||||||
Upvalue* upvalue = (Upvalue*)obj;
|
Upvalue* upvalue = (Upvalue*)obj;
|
||||||
@ -409,6 +418,16 @@ Closure* newClosure(PKVM* vm, Function* fn) {
|
|||||||
return closure;
|
return closure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MethodBind* newMethodBind(PKVM* vm, Closure* method) {
|
||||||
|
MethodBind* mb = ALLOCATE(vm, MethodBind);
|
||||||
|
varInitObject(&mb->_super, vm, OBJ_METHOD_BIND);
|
||||||
|
|
||||||
|
mb->method = method;
|
||||||
|
mb->instance = VAR_UNDEFINED;
|
||||||
|
|
||||||
|
return mb;
|
||||||
|
}
|
||||||
|
|
||||||
Upvalue* newUpvalue(PKVM* vm, Var* value) {
|
Upvalue* newUpvalue(PKVM* vm, Var* value) {
|
||||||
Upvalue* upvalue = ALLOCATE(vm, Upvalue);
|
Upvalue* upvalue = ALLOCATE(vm, Upvalue);
|
||||||
varInitObject(&upvalue->_super, vm, OBJ_UPVALUE);
|
varInitObject(&upvalue->_super, vm, OBJ_UPVALUE);
|
||||||
@ -920,6 +939,10 @@ static uint32_t _hashObject(Object* obj) {
|
|||||||
return utilHashNumber(range->from) ^ utilHashNumber(range->to);
|
return utilHashNumber(range->from) ^ utilHashNumber(range->to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case OBJ_CLASS: {
|
||||||
|
return utilHashBits( (int64_t) obj);
|
||||||
|
}
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1168,6 +1191,11 @@ void freeObject(PKVM* vm, Object* self) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case OBJ_METHOD_BIND: {
|
||||||
|
DEALLOCATE(vm, self, MethodBind);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
case OBJ_UPVALUE: {
|
case OBJ_UPVALUE: {
|
||||||
DEALLOCATE(vm, self, Upvalue);
|
DEALLOCATE(vm, self, Upvalue);
|
||||||
return;
|
return;
|
||||||
@ -1309,6 +1337,7 @@ PkVarType getObjPkVarType(ObjectType type) {
|
|||||||
case OBJ_MODULE: return PK_MODULE;
|
case OBJ_MODULE: return PK_MODULE;
|
||||||
case OBJ_FUNC: UNREACHABLE();
|
case OBJ_FUNC: UNREACHABLE();
|
||||||
case OBJ_CLOSURE: return PK_CLOSURE;
|
case OBJ_CLOSURE: return PK_CLOSURE;
|
||||||
|
case OBJ_METHOD_BIND: return PK_METHOD_BIND;
|
||||||
case OBJ_UPVALUE: UNREACHABLE();
|
case OBJ_UPVALUE: UNREACHABLE();
|
||||||
case OBJ_FIBER: return PK_FIBER;
|
case OBJ_FIBER: return PK_FIBER;
|
||||||
case OBJ_CLASS: return PK_CLASS;
|
case OBJ_CLASS: return PK_CLASS;
|
||||||
@ -1327,15 +1356,16 @@ ObjectType getPkVarObjType(PkVarType type) {
|
|||||||
case PK_NUMBER:
|
case PK_NUMBER:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
|
|
||||||
case PK_STRING: return OBJ_STRING;
|
case PK_STRING: return OBJ_STRING;
|
||||||
case PK_LIST: return OBJ_LIST;
|
case PK_LIST: return OBJ_LIST;
|
||||||
case PK_MAP: return OBJ_MAP;
|
case PK_MAP: return OBJ_MAP;
|
||||||
case PK_RANGE: return OBJ_RANGE;
|
case PK_RANGE: return OBJ_RANGE;
|
||||||
case PK_MODULE: return OBJ_MODULE;
|
case PK_MODULE: return OBJ_MODULE;
|
||||||
case PK_CLOSURE: return OBJ_CLOSURE;
|
case PK_CLOSURE: return OBJ_CLOSURE;
|
||||||
case PK_FIBER: return OBJ_FIBER;
|
case PK_METHOD_BIND: return OBJ_METHOD_BIND;
|
||||||
case PK_CLASS: return OBJ_CLASS;
|
case PK_FIBER: return OBJ_FIBER;
|
||||||
case PK_INSTANCE: return OBJ_INST;
|
case PK_CLASS: return OBJ_CLASS;
|
||||||
|
case PK_INSTANCE: return OBJ_INST;
|
||||||
}
|
}
|
||||||
|
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
@ -1365,6 +1395,7 @@ const char* getObjectTypeName(ObjectType type) {
|
|||||||
case OBJ_MODULE: return "Module";
|
case OBJ_MODULE: return "Module";
|
||||||
case OBJ_FUNC: return "Func";
|
case OBJ_FUNC: return "Func";
|
||||||
case OBJ_CLOSURE: return "Closure";
|
case OBJ_CLOSURE: return "Closure";
|
||||||
|
case OBJ_METHOD_BIND: return "MethodBind";
|
||||||
case OBJ_UPVALUE: return "Upvalue";
|
case OBJ_UPVALUE: return "Upvalue";
|
||||||
case OBJ_FIBER: return "Fiber";
|
case OBJ_FIBER: return "Fiber";
|
||||||
case OBJ_CLASS: return "Class";
|
case OBJ_CLASS: return "Class";
|
||||||
@ -1472,7 +1503,7 @@ bool isValuesEqual(Var v1, Var v2) {
|
|||||||
|
|
||||||
bool isObjectHashable(ObjectType type) {
|
bool isObjectHashable(ObjectType type) {
|
||||||
// Only String and Range are hashable (since they're immutable).
|
// Only String and Range are hashable (since they're immutable).
|
||||||
return type == OBJ_STRING || type == OBJ_RANGE;
|
return type == OBJ_STRING || type == OBJ_RANGE || type == OBJ_CLASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will prevent recursive list/map from crash when calling to_string, by
|
// This will prevent recursive list/map from crash when calling to_string, by
|
||||||
@ -1681,7 +1712,7 @@ static void _toStringInternal(PKVM* vm, const Var v, pkByteBuffer* buff,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case OBJ_FUNC: {
|
case OBJ_FUNC: {
|
||||||
const Function* fn = (const Function*)obj;
|
const Function* fn = (const Function*) obj;
|
||||||
pkByteBufferAddString(buff, vm, "[Func:", 6);
|
pkByteBufferAddString(buff, vm, "[Func:", 6);
|
||||||
pkByteBufferAddString(buff, vm, fn->name, (uint32_t)strlen(fn->name));
|
pkByteBufferAddString(buff, vm, fn->name, (uint32_t)strlen(fn->name));
|
||||||
pkByteBufferWrite(buff, vm, ']');
|
pkByteBufferWrite(buff, vm, ']');
|
||||||
@ -1689,16 +1720,24 @@ static void _toStringInternal(PKVM* vm, const Var v, pkByteBuffer* buff,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case OBJ_CLOSURE: {
|
case OBJ_CLOSURE: {
|
||||||
const Closure* closure = (const Closure*)obj;
|
const Closure* closure = (const Closure*) obj;
|
||||||
pkByteBufferAddString(buff, vm, "[Closure:", 9);
|
pkByteBufferAddString(buff, vm, "[Closure:", 9);
|
||||||
pkByteBufferAddString(buff, vm, closure->fn->name,
|
pkByteBufferAddString(buff, vm, closure->fn->name,
|
||||||
(uint32_t)strlen(closure->fn->name));
|
(uint32_t)strlen(closure->fn->name));
|
||||||
pkByteBufferWrite(buff, vm, ']');
|
pkByteBufferWrite(buff, vm, ']');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case OBJ_METHOD_BIND: {
|
||||||
|
const MethodBind* mb = (const MethodBind*) obj;
|
||||||
|
pkByteBufferAddString(buff, vm, "[MethodBind:", 12);
|
||||||
|
pkByteBufferAddString(buff, vm, mb->method->fn->name,
|
||||||
|
(uint32_t)strlen(mb->method->fn->name));
|
||||||
|
pkByteBufferWrite(buff, vm, ']');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
case OBJ_FIBER: {
|
case OBJ_FIBER: {
|
||||||
const Fiber* fb = (const Fiber*)obj;
|
const Fiber* fb = (const Fiber*) obj;
|
||||||
pkByteBufferAddString(buff, vm, "[Fiber:", 7);
|
pkByteBufferAddString(buff, vm, "[Fiber:", 7);
|
||||||
pkByteBufferAddString(buff, vm, fb->closure->fn->name,
|
pkByteBufferAddString(buff, vm, fb->closure->fn->name,
|
||||||
(uint32_t)strlen(fb->closure->fn->name));
|
(uint32_t)strlen(fb->closure->fn->name));
|
||||||
@ -1784,6 +1823,7 @@ bool toBool(Var v) {
|
|||||||
case OBJ_MODULE:
|
case OBJ_MODULE:
|
||||||
case OBJ_FUNC:
|
case OBJ_FUNC:
|
||||||
case OBJ_CLOSURE:
|
case OBJ_CLOSURE:
|
||||||
|
case OBJ_METHOD_BIND:
|
||||||
case OBJ_UPVALUE:
|
case OBJ_UPVALUE:
|
||||||
case OBJ_FIBER:
|
case OBJ_FIBER:
|
||||||
case OBJ_CLASS:
|
case OBJ_CLASS:
|
||||||
|
@ -192,6 +192,7 @@ typedef struct Range Range;
|
|||||||
typedef struct Module Module;
|
typedef struct Module Module;
|
||||||
typedef struct Function Function;
|
typedef struct Function Function;
|
||||||
typedef struct Closure Closure;
|
typedef struct Closure Closure;
|
||||||
|
typedef struct MethodBind MethodBind;
|
||||||
typedef struct Upvalue Upvalue;
|
typedef struct Upvalue Upvalue;
|
||||||
typedef struct Fiber Fiber;
|
typedef struct Fiber Fiber;
|
||||||
typedef struct Class Class;
|
typedef struct Class Class;
|
||||||
@ -223,6 +224,7 @@ typedef enum {
|
|||||||
OBJ_MODULE,
|
OBJ_MODULE,
|
||||||
OBJ_FUNC,
|
OBJ_FUNC,
|
||||||
OBJ_CLOSURE,
|
OBJ_CLOSURE,
|
||||||
|
OBJ_METHOD_BIND,
|
||||||
OBJ_UPVALUE,
|
OBJ_UPVALUE,
|
||||||
OBJ_FIBER,
|
OBJ_FIBER,
|
||||||
OBJ_CLASS,
|
OBJ_CLASS,
|
||||||
@ -402,7 +404,17 @@ struct Closure {
|
|||||||
|
|
||||||
Function* fn;
|
Function* fn;
|
||||||
Upvalue* upvalues[DYNAMIC_TAIL_ARRAY];
|
Upvalue* upvalues[DYNAMIC_TAIL_ARRAY];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Method bounds are first class callable of methods. That are bound to an
|
||||||
|
// instace which will be used as the self when the underlying method invoked.
|
||||||
|
// If the vallue [instance] is VAR_UNDEFINED it's unbound and cannot be
|
||||||
|
// called.
|
||||||
|
struct MethodBind {
|
||||||
|
Object _super;
|
||||||
|
|
||||||
|
Closure* method;
|
||||||
|
Var instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
// In addition to locals (which lives on the stack), a closure has upvalues.
|
// In addition to locals (which lives on the stack), a closure has upvalues.
|
||||||
@ -594,6 +606,8 @@ Module* newModule(PKVM* vm);
|
|||||||
|
|
||||||
Closure* newClosure(PKVM* vm, Function* fn);
|
Closure* newClosure(PKVM* vm, Function* fn);
|
||||||
|
|
||||||
|
MethodBind* newMethodBind(PKVM* vm, Closure* method);
|
||||||
|
|
||||||
Upvalue* newUpvalue(PKVM* vm, Var* value);
|
Upvalue* newUpvalue(PKVM* vm, Var* value);
|
||||||
|
|
||||||
Fiber* newFiber(PKVM* vm, Closure* closure);
|
Fiber* newFiber(PKVM* vm, Closure* closure);
|
||||||
|
@ -1223,6 +1223,15 @@ L_do_call:
|
|||||||
if (IS_OBJ_TYPE(callable, OBJ_CLOSURE)) {
|
if (IS_OBJ_TYPE(callable, OBJ_CLOSURE)) {
|
||||||
closure = (const Closure*)AS_OBJ(callable);
|
closure = (const Closure*)AS_OBJ(callable);
|
||||||
|
|
||||||
|
} else if (IS_OBJ_TYPE(callable, OBJ_METHOD_BIND)) {
|
||||||
|
const MethodBind* mb = (const MethodBind*) AS_OBJ(callable);
|
||||||
|
if (IS_UNDEF(mb->instance)) {
|
||||||
|
RUNTIME_ERROR(newString(vm, "Cannot call an unbound method."));
|
||||||
|
CHECK_ERROR();
|
||||||
|
}
|
||||||
|
fiber->self = mb->instance;
|
||||||
|
closure = mb->method;
|
||||||
|
|
||||||
} else if (IS_OBJ_TYPE(callable, OBJ_CLASS)) {
|
} else if (IS_OBJ_TYPE(callable, OBJ_CLASS)) {
|
||||||
Class* cls = (Class*)AS_OBJ(callable);
|
Class* cls = (Class*)AS_OBJ(callable);
|
||||||
|
|
||||||
@ -1422,6 +1431,7 @@ L_do_call:
|
|||||||
case OBJ_MODULE:
|
case OBJ_MODULE:
|
||||||
case OBJ_FUNC:
|
case OBJ_FUNC:
|
||||||
case OBJ_CLOSURE:
|
case OBJ_CLOSURE:
|
||||||
|
case OBJ_METHOD_BIND:
|
||||||
case OBJ_UPVALUE:
|
case OBJ_UPVALUE:
|
||||||
case OBJ_FIBER:
|
case OBJ_FIBER:
|
||||||
case OBJ_CLASS:
|
case OBJ_CLASS:
|
||||||
|
@ -180,6 +180,7 @@ enum PkVarType {
|
|||||||
PK_RANGE,
|
PK_RANGE,
|
||||||
PK_MODULE,
|
PK_MODULE,
|
||||||
PK_CLOSURE,
|
PK_CLOSURE,
|
||||||
|
PK_METHOD_BIND,
|
||||||
PK_FIBER,
|
PK_FIBER,
|
||||||
PK_CLASS,
|
PK_CLASS,
|
||||||
PK_INSTANCE,
|
PK_INSTANCE,
|
||||||
|
@ -134,7 +134,7 @@ DEF(_fileOpen,
|
|||||||
"Opens a file at the [path] with the [mode]. Path should be either "
|
"Opens a file at the [path] with the [mode]. Path should be either "
|
||||||
"absolute or relative to the current working directory. and [mode] can be"
|
"absolute or relative to the current working directory. and [mode] can be"
|
||||||
"'r', 'w', 'a' in combination with 'b' (binary) and/or '+' (extended).\n"
|
"'r', 'w', 'a' in combination with 'b' (binary) and/or '+' (extended).\n"
|
||||||
"\n"
|
"```\n"
|
||||||
" mode | If already exists | If does not exist |\n"
|
" mode | If already exists | If does not exist |\n"
|
||||||
" -----+-------------------+-------------------|\n"
|
" -----+-------------------+-------------------|\n"
|
||||||
" 'r' | read from start | failure to open |\n"
|
" 'r' | read from start | failure to open |\n"
|
||||||
@ -143,7 +143,7 @@ DEF(_fileOpen,
|
|||||||
" 'r+' | read from start | error |\n"
|
" 'r+' | read from start | error |\n"
|
||||||
" 'w+' | destroy contents | create new |\n"
|
" 'w+' | destroy contents | create new |\n"
|
||||||
" 'a+' | write to end | create new |\n"
|
" 'a+' | write to end | create new |\n"
|
||||||
"") {
|
"```") {
|
||||||
|
|
||||||
int argc = pkGetArgc(vm);
|
int argc = pkGetArgc(vm);
|
||||||
if (!pkCheckArgcRange(vm, argc, 1, 2)) return;
|
if (!pkCheckArgcRange(vm, argc, 1, 2)) return;
|
||||||
@ -441,7 +441,7 @@ DEF(_open,
|
|||||||
"Opens a file at the [path] with the [mode]. Path should be either "
|
"Opens a file at the [path] with the [mode]. Path should be either "
|
||||||
"absolute or relative to the current working directory. and [mode] can be"
|
"absolute or relative to the current working directory. and [mode] can be"
|
||||||
"'r', 'w', 'a' in combination with 'b' (binary) and/or '+' (extended).\n"
|
"'r', 'w', 'a' in combination with 'b' (binary) and/or '+' (extended).\n"
|
||||||
"\n"
|
"```\n"
|
||||||
" mode | If already exists | If does not exist |\n"
|
" mode | If already exists | If does not exist |\n"
|
||||||
" -----+-------------------+-------------------|\n"
|
" -----+-------------------+-------------------|\n"
|
||||||
" 'r' | read from start | failure to open |\n"
|
" 'r' | read from start | failure to open |\n"
|
||||||
@ -450,7 +450,7 @@ DEF(_open,
|
|||||||
" 'r+' | read from start | error |\n"
|
" 'r+' | read from start | error |\n"
|
||||||
" 'w+' | destroy contents | create new |\n"
|
" 'w+' | destroy contents | create new |\n"
|
||||||
" 'a+' | write to end | create new |\n"
|
" 'a+' | write to end | create new |\n"
|
||||||
"") {
|
"```") {
|
||||||
pkReserveSlots(vm, 3);
|
pkReserveSlots(vm, 3);
|
||||||
|
|
||||||
// slots[1] = path
|
// slots[1] = path
|
||||||
|
@ -182,5 +182,31 @@ def foo(p1, p2, p3) end
|
|||||||
assert(foo.name == "foo")
|
assert(foo.name == "foo")
|
||||||
assert(foo.arity == 3)
|
assert(foo.arity == 3)
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
## METHOD BIND
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
class Foo
|
||||||
|
def bar()
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
foo = Foo()
|
||||||
|
bar = foo.bar
|
||||||
|
assert(bar() == foo)
|
||||||
|
|
||||||
|
class Bar
|
||||||
|
def baz()
|
||||||
|
"baz doc string"
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
bar = Bar()
|
||||||
|
bz = Bar.baz
|
||||||
|
assert(bz._docs == "baz doc string")
|
||||||
|
bz.bind(bar)()
|
||||||
|
|
||||||
## If we got here, that means all test were passed.
|
## If we got here, that means all test were passed.
|
||||||
print('All TESTS PASSED')
|
print('All TESTS PASSED')
|
||||||
|
@ -21,6 +21,8 @@ print(a)
|
|||||||
b = B()
|
b = B()
|
||||||
assert((b is B) and (b is A))
|
assert((b is B) and (b is A))
|
||||||
|
|
||||||
|
assert(B.parent == A)
|
||||||
|
|
||||||
class Shape
|
class Shape
|
||||||
def display()
|
def display()
|
||||||
return "${self.name} shape"
|
return "${self.name} shape"
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
## from either mylib.so, or mylib.dll
|
## from either mylib.so, or mylib.dll
|
||||||
import mylib
|
import mylib
|
||||||
|
|
||||||
if __name__ == "__main__"
|
if _name == "@main"
|
||||||
## Call the registered function.
|
## Call the registered function.
|
||||||
print('mylib.hello() = ${mylib.hello()}')
|
print('mylib.hello() = ${mylib.hello()}')
|
||||||
end
|
end
|
||||||
|
@ -100,6 +100,7 @@ end
|
|||||||
|
|
||||||
## -------------------------------------------------
|
## -------------------------------------------------
|
||||||
|
|
||||||
## if __name__ == '__main__' ;)
|
if _name == '@main'
|
||||||
main()
|
main()
|
||||||
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user