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
|
{ 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.
|
||||||
|
|
12
http.spl
12
http.spl
|
@ -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
38
std.spl
|
@ -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 {
|
||||||
|
|
6
test.spl
6
test.spl
|
@ -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 {
|
||||||
|
|
Loading…
Add table
Reference in a new issue