Deprecate _ function, Add section on postfix args to README, Add nconcat function.
This commit is contained in:
parent
0689bdbea0
commit
1dce63794b
4 changed files with 90 additions and 24 deletions
58
README.md
58
README.md
|
@ -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.
|
||||
|
|
12
http.spl
12
http.spl
|
@ -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
38
std.spl
|
@ -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 {
|
||||
|
|
6
test.spl
6
test.spl
|
@ -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 {
|
||||
|
|
Loading…
Add table
Reference in a new issue