Deprecate _ function, Add section on postfix args to README, Add nconcat function.

This commit is contained in:
Daniella / Tove 2023-04-08 09:51:40 +02:00
parent 0689bdbea0
commit 1dce63794b
Signed by: TudbuT
GPG key ID: 7D63D5634B7C417F
4 changed files with 90 additions and 24 deletions

View file

@ -10,6 +10,7 @@ func main { mega | with args ;
{ str | " " concat } swap:map { str | " " concat } swap:map
&print swap:foreach &print swap:foreach
"" println "" println
println <{ "and with that, we're done" }
0 0
} }
``` ```
@ -130,9 +131,7 @@ func main { mega | with args ;
It sure does look like it, doesn't it? `swap` swaps the topmost two values on It sure does look like it, doesn't it? `swap` swaps the topmost two values on
the stack. `a b -> b a`. That means we are actually calling to our iterator. the stack. `a b -> b a`. That means we are actually calling to our iterator.
The closure and the iterator are swapped before the call is made. `swap:map` The closure and the iterator are swapped before the call is made. `swap:map`
is a more concise way of writing `swap _:map`. The underscore is used as a is a more concise way of writing `swap :map`.
placeholder for the topmost value of the stack when making method calls,
because `swap :map` would try to call map on an empty expression.
The map function on the iterator (which is available through `:iter` on most The map function on the iterator (which is available through `:iter` on most
collection constructs) is used to apply a function to all items in the collection constructs) is used to apply a function to all items in the
@ -176,5 +175,58 @@ func main { mega | with args ;
```java ```java
for(int i = 0; i < 5; i++) { println((String) i * 5); } for(int i = 0; i < 5; i++) { println((String) i * 5); }
``` ```
- SPL actually isn't fully concatenative. It supports postfix arguments as well:
```js
println <{ "and with that, we're done" }
```
This is actually not a special interpreter feature, more so is it a special
lexer feature. This is 100% equivalent with the non-postfix version, where the
string is right before the `println`.
The same can be done for object calls. Let's rewrite the previous code with
postfix:
```js
Range:new <{ 0 5 }
:iter
:map <{ { | 5 * } }
:foreach <{ { | _str println } }
```
I lied. This is now no longer 100% equivalent. Let's look at what happens
under the hood.
```asm
call Range
objpush
const mega 0
const mega 5
objpop
objcall new
objcall iter
objpush
const func 0
const mega 5
call *
end
objpop
objcall map
objpush
const func 0
call _str
call println
end
objpop
call foreach
```
You can see there are now `objpush` and `objpop` instructions. This is doing
the job that `swap` used to do in our previous example. However, swap can only
swap the topmost values, but postfix arguments allow any amount. That's why
there is a special instruction just for that. It can also be used through AST
modifications, but there is no way to get it in normal language use as it can
cause interpreter panics when they are used wrongly.
`objpush` and `objpop` operate on a separate stack, called the objcall stack,
as opposed to the main object stack.
More of this tutorial to follow. More of this tutorial to follow.

View file

@ -37,24 +37,24 @@ construct net:http:Request {
def response net:http:Response:new =response def response net:http:Response:new =response
this:method:to-bytes stream:write-exact; this:method:to-bytes stream:write-exact;
" " _:to-bytes stream:write-exact; " " :to-bytes stream:write-exact;
this:path:to-bytes stream:write-exact; this:path:to-bytes stream:write-exact;
" HTTP/1.0\r\n" _:to-bytes stream:write-exact; " HTTP/1.0\r\n" :to-bytes stream:write-exact;
"Host: " _:to-bytes stream:write-exact; "Host: " :to-bytes stream:write-exact;
this:host:to-bytes stream:write-exact; this:host:to-bytes stream:write-exact;
"\r\nConnection: Close\r\nUser-Agent: http.spl v0.1 2023-03 (spl@mail.tudbut.de)\r\n" "\r\nConnection: Close\r\nUser-Agent: http.spl v0.1 2023-03 (spl@mail.tudbut.de)\r\n"
_:to-bytes stream:write-exact; :to-bytes stream:write-exact;
{ | with header ; { | with header ;
header:to-bytes stream:write-exact; header:to-bytes stream:write-exact;
"\r\n" stream:write-exact; "\r\n" stream:write-exact;
} this:headers:foreach } this:headers:foreach
"Content-Length: " _:to-bytes stream:write-exact; "Content-Length: " :to-bytes stream:write-exact;
def body this:body:to-bytes =body def body this:body:to-bytes =body
body:len _str:to-bytes stream:write-exact; body:len _str:to-bytes stream:write-exact;
"\r\n\r\n" _:to-bytes stream:write-exact; "\r\n\r\n" :to-bytes stream:write-exact;
body stream:write-exact; body stream:write-exact;
stream:flush; stream:flush;

38
std.spl
View file

@ -124,14 +124,14 @@ construct List {
array this:=array array this:=array
this this
} }
foreach { | _:array:foreach } foreach { | :array:foreach }
get { any | _:array:get } get { any | :array:get }
sget { any|null | _:array:sget } sget { any|null | :array:sget }
len { mega | _:array:len } len { mega | :array:len }
set { any | _:array:set } set { any | :array:set }
to-stack { .. | _:array:to-stack } to-stack { .. | :array:to-stack }
to-str { str | _:array:to-str } to-str { str | :array:to-str }
sub { [any] | _:array:sub } sub { [any] | :array:sub }
} }
construct _GrowingArray { construct _GrowingArray {
; ;
@ -216,7 +216,7 @@ construct MicroMap {
get-entry { [any,any]|null | with key this ; get-entry { [any,any]|null | with key this ;
this:pairs:iter this:pairs:iter
{ mega | 0 swap:get key eq } swap:filter { mega | 0 swap:get key eq } swap:filter
_:next :next
} }
get-or-create-entry { [any,any] | with key this ; get-or-create-entry { [any,any] | with key this ;
{ [any,any] | { [any,any] |
@ -227,7 +227,7 @@ construct MicroMap {
this:pairs:iter this:pairs:iter
{ mega | 0 swap:get key eq } swap:filter { mega | 0 swap:get key eq } swap:filter
{ any | 1 swap:get } swap:map { any | 1 swap:get } swap:map
_:next :next
} }
set { any | with key val this ; set { any | with key val this ;
val 1 (key this:get-or-create-entry):set val 1 (key this:get-or-create-entry):set
@ -235,7 +235,7 @@ construct MicroMap {
remove { any | with key this ; remove { any | with key this ;
this:pairs:iter this:pairs:iter
{ mega | 0 swap:get key eq not } swap:filter { mega | 0 swap:get key eq not } swap:filter
_:collect :collect
List:new:from List:new:from
=pairs =pairs
} }
@ -310,6 +310,14 @@ func concat { str | with a b ;
a _array b _array aadd _str a _array b _array aadd _str
} }
func nconcat { str | with amt ;
_array
(amt 1 -):foreach <{ { | pop
swap _array swap aadd
} }
_str
}
func handle-panic { | with msg trace ; func handle-panic { | with msg trace ;
program-name dup if { program-name dup if {
program-name print " panicked at:" println program-name print " panicked at:" println
@ -381,7 +389,13 @@ func -- { mega |
1 - 1 -
} }
func _ { | } def _'has-been-called 0 =_'has-been-called
func _ { |
_'has-been-called not if {
"WARN: The _ function is deprecated!" println
1 =_'has-been-called
}
}
func call-main-on-file { | with file ; func call-main-on-file { | with file ;
catch { catch {

View file

@ -75,7 +75,7 @@ func main { int | with args ;
0 5 Range:new:iter 0 5 Range:new:iter
{ | pop 10 } swap:map { | pop 10 } swap:map
_:sum :sum
_str println _str println
"" println "" println
@ -104,12 +104,12 @@ func main { int | with args ;
"testing stream" println "testing stream" println
def file "test.txt" 1 StreamTypes:file:create =file def file "test.txt" 1 StreamTypes:file:create =file
"hi\n" _:to-bytes file:write-exact; "hi\n" :to-bytes file:write-exact;
file:close null =file file:close null =file
"" println "" println
"testing split" println "testing split" println
{ | println } (" " "hello how are you" _:split):foreach { | println } (" " "hello how are you" :split):foreach
"" println "" println
catch { catch {