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
&print swap:foreach
"" println
println <{ "and with that, we're done" }
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
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`
is a more concise way of writing `swap _:map`. The underscore is used as a
placeholder for the topmost value of the stack when making method calls,
because `swap :map` would try to call map on an empty expression.
is a more concise way of writing `swap :map`.
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
@ -176,5 +175,58 @@ func main { mega | with args ;
```java
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.

View file

@ -37,24 +37,24 @@ construct net:http:Request {
def response net:http:Response:new =response
this:method:to-bytes stream:write-exact;
" " _:to-bytes stream:write-exact;
" " :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;
"\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 ;
header:to-bytes stream:write-exact;
"\r\n" stream:write-exact;
} this:headers:foreach
"Content-Length: " _:to-bytes stream:write-exact;
"Content-Length: " :to-bytes stream:write-exact;
def body this:body:to-bytes =body
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;
stream:flush;

38
std.spl
View file

@ -124,14 +124,14 @@ construct List {
array this:=array
this
}
foreach { | _:array:foreach }
get { any | _:array:get }
sget { any|null | _:array:sget }
len { mega | _:array:len }
set { any | _:array:set }
to-stack { .. | _:array:to-stack }
to-str { str | _:array:to-str }
sub { [any] | _:array:sub }
foreach { | :array:foreach }
get { any | :array:get }
sget { any|null | :array:sget }
len { mega | :array:len }
set { any | :array:set }
to-stack { .. | :array:to-stack }
to-str { str | :array:to-str }
sub { [any] | :array:sub }
}
construct _GrowingArray {
;
@ -216,7 +216,7 @@ construct MicroMap {
get-entry { [any,any]|null | with key this ;
this:pairs:iter
{ mega | 0 swap:get key eq } swap:filter
_:next
:next
}
get-or-create-entry { [any,any] | with key this ;
{ [any,any] |
@ -227,7 +227,7 @@ construct MicroMap {
this:pairs:iter
{ mega | 0 swap:get key eq } swap:filter
{ any | 1 swap:get } swap:map
_:next
:next
}
set { any | with key val this ;
val 1 (key this:get-or-create-entry):set
@ -235,7 +235,7 @@ construct MicroMap {
remove { any | with key this ;
this:pairs:iter
{ mega | 0 swap:get key eq not } swap:filter
_:collect
:collect
List:new:from
=pairs
}
@ -310,6 +310,14 @@ func concat { str | with a b ;
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 ;
program-name dup if {
program-name print " panicked at:" println
@ -381,7 +389,13 @@ func -- { mega |
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 ;
catch {

View file

@ -75,7 +75,7 @@ func main { int | with args ;
0 5 Range:new:iter
{ | pop 10 } swap:map
_:sum
:sum
_str println
"" println
@ -104,12 +104,12 @@ func main { int | with args ;
"testing stream" println
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
"" println
"testing split" println
{ | println } (" " "hello how are you" _:split):foreach
{ | println } (" " "hello how are you" :split):foreach
"" println
catch {