List notations/pattern matching

This commit is contained in:
Dmitry Boulytchev 2019-03-07 21:12:43 +03:00
parent 4879a02753
commit e16fb72a9e
8 changed files with 128 additions and 20 deletions

View file

@ -0,0 +1,8 @@
> 0
15
15
1
2
3
4
5

28
regression/test051.expr Normal file
View file

@ -0,0 +1,28 @@
fun sum (l) {
case l of
{} -> return 0
| h : t -> return (h + sum (t))
esac
}
fun print_list (l) {
case l of
{} -> skip
| h : t -> write (h); print_list (t)
esac
}
fun array_to_list (a) local l, i {
l := {};
for i := a.length, i > 0, i := i-1 do
l := a[i-1] : l
od;
return l
}
n := read ();
write (sum ({}));
write (sum ({1, 2, 3, 4, 5}));
write (sum (1:2:3:4:5:{}));
print_list (array_to_list ([1, 2, 3, 4, 5]))

1
regression/test051.input Normal file
View file

@ -0,0 +1 @@
0

View file

@ -0,0 +1,4 @@
0
{1, 2, 3, 4}
{{1}, {2, 3}, {4, {5, 6}}}
{1, 2, 3, 4}

View file

@ -0,0 +1,10 @@
lists := [
{},
{1, 2, 3, 4},
{{1}, {2, 3}, {4, {5, 6}}},
1 : 2 : 3 : 4 : {}
];
for i := 0, i<lists.length, i:=i+1 do
printf ("%s\n", lists[i].string)
od

View file

@ -0,0 +1 @@
0

View file

@ -134,17 +134,39 @@ static void printValue (void *p) {
printStringBuf ("]"); printStringBuf ("]");
break; break;
case SEXP_TAG: case SEXP_TAG: {
printStringBuf ("%s", de_hash (TO_SEXP(p)->tag)); char * tag = de_hash (TO_SEXP(p)->tag);
if (LEN(a->tag)) {
printStringBuf (" ("); if (strcmp (tag, "cons") == 0) {
for (i = 0; i < LEN(a->tag); i++) { data *b = a;
printValue ((void*)((int*) a->contents)[i]);
if (i != LEN(a->tag) - 1) printStringBuf (", "); printStringBuf ("{");
while (LEN(a->tag)) {
printValue ((void*)((int*) b->contents)[0]);
b = (data*)((int*) b->contents)[1];
if (! UNBOXED(b)) {
printStringBuf (", ");
b = TO_DATA(b);
}
else break;
} }
printStringBuf (")");
printStringBuf ("}");
} }
break; else {
printStringBuf ("%s", tag);
if (LEN(a->tag)) {
printStringBuf (" (");
for (i = 0; i < LEN(a->tag); i++) {
printValue ((void*)((int*) a->contents)[i]);
if (i != LEN(a->tag) - 1) printStringBuf (", ");
}
printStringBuf (")");
}
}
}
break;
default: default:
printStringBuf ("*** invalid tag: %x ***", TAG(a->tag)); printStringBuf ("*** invalid tag: %x ***", TAG(a->tag));
@ -485,7 +507,7 @@ static void extend_spaces (void) {
void *p1 = mremap(from_space.begin, SPACE_SIZE, 2*SPACE_SIZE, 0); void *p1 = mremap(from_space.begin, SPACE_SIZE, 2*SPACE_SIZE, 0);
void *p2 = mremap(to_space.begin , SPACE_SIZE, 2*SPACE_SIZE, 0); void *p2 = mremap(to_space.begin , SPACE_SIZE, 2*SPACE_SIZE, 0);
if (p1 == MAP_FAILED || p2 == MAP_FAILED) { if (p1 == MAP_FAILED || p2 == MAP_FAILED) {
perror("EROOR: extend_spaces: mmap failed\n"); perror("ERROR: extend_spaces: mmap failed\n");
exit (1); exit (1);
} }
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
@ -623,7 +645,7 @@ extern void init_pool (void) {
MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0); MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
if (to_space.begin == MAP_FAILED || if (to_space.begin == MAP_FAILED ||
from_space.begin == MAP_FAILED) { from_space.begin == MAP_FAILED) {
perror("EROOR: init_pool: mmap failed\n"); perror("ERROR: init_pool: mmap failed\n");
exit (1); exit (1);
} }
from_space.current = from_space.begin; from_space.current = from_space.begin;

View file

@ -46,7 +46,21 @@ module Value =
| Array a -> let n = Array.length a in | Array a -> let n = Array.length a in
append "["; Array.iteri (fun i a -> (if i > 0 then append ", "); inner a) a; append "]" append "["; Array.iteri (fun i a -> (if i > 0 then append ", "); inner a) a; append "]"
| Sexp (t, a) -> let n = List.length a in | Sexp (t, a) -> let n = List.length a in
append t; (if n > 0 then (append " ("; List.iteri (fun i a -> (if i > 0 then append ", "); inner a) a; append ")")) if t = "cons"
then (
append "{";
let rec inner_list = function
| [] -> ()
| [x; Int 0] -> inner x
| [x; Sexp ("cons", a)] -> inner x; append ", "; inner_list a
in inner_list a;
append "}"
)
else (
append t;
(if n > 0 then (append " ("; List.iteri (fun i a -> (if i > 0 then append ", "); inner a) a;
append ")"))
)
in in
inner v; inner v;
Bytes.of_string @@ Buffer.contents buf Bytes.of_string @@ Buffer.contents buf
@ -252,17 +266,19 @@ module Expr =
List.map (fun s -> ostap(- $(s)), List.map (fun s -> ostap(- $(s)),
(fun x y -> (fun x y ->
match s with match s with
| ":" -> Sexp ("cons", [x; y])
| "++" -> Call ("strcat", [x; y]) | "++" -> Call ("strcat", [x; y])
| _ -> Binop (s, x, y) | _ -> Binop (s, x, y)
) )
) s ) s
) )
[| [|
`Lefta, ["!!"]; `Righta, [":"];
`Lefta, ["&&"]; `Lefta , ["!!"];
`Nona , ["=="; "!="; "<="; "<"; ">="; ">"]; `Lefta , ["&&"];
`Lefta, ["++"; "+" ; "-"]; `Nona , ["=="; "!="; "<="; "<"; ">="; ">"];
`Lefta, ["*" ; "/"; "%"]; `Lefta , ["++"; "+" ; "-"];
`Lefta , ["*" ; "/"; "%"];
|] |]
) )
primary); primary);
@ -273,6 +289,10 @@ module Expr =
| s:STRING {String (String.sub s 1 (String.length s - 2))} | s:STRING {String (String.sub s 1 (String.length s - 2))}
| c:CHAR {Const (Char.code c)} | c:CHAR {Const (Char.code c)}
| "[" es:!(Util.list0)[parse] "]" {Array es} | "[" es:!(Util.list0)[parse] "]" {Array es}
| "{" es:!(Util.list0)[parse] "}" {match es with
| [] -> Const 0
| _ -> List.fold_right (fun x acc -> Sexp ("cons", [x; acc])) es (Const 0)
}
| t:UIDENT args:(-"(" !(Util.list)[parse] -")")? {Sexp (t, match args with None -> [] | Some args -> args)} | t:UIDENT args:(-"(" !(Util.list)[parse] -")")? {Sexp (t, match args with None -> [] | Some args -> args)}
| x:LIDENT s:("(" args:!(Util.list0)[parse] ")" {Call (x, args)} | empty {Var x}) {s} | x:LIDENT s:("(" args:!(Util.list0)[parse] ")" {Call (x, args)} | empty {Var x}) {s}
| -"(" parse -")" | -"(" parse -")"
@ -306,9 +326,22 @@ module Stmt =
(* Pattern parser *) (* Pattern parser *)
ostap ( ostap (
parse: parse:
%"_" {Wildcard} !(Ostap.Util.expr
(fun x -> x)
(Array.map (fun (a, s) ->
a,
List.map (fun s -> ostap(- $(s)), (fun x y -> Sexp ("cons", [x; y]))) s)
[|`Righta, [":"]|]
)
primary);
primary:
%"_" {Wildcard}
| t:UIDENT ps:(-"(" !(Util.list)[parse] -")")? {Sexp (t, match ps with None -> [] | Some ps -> ps)} | t:UIDENT ps:(-"(" !(Util.list)[parse] -")")? {Sexp (t, match ps with None -> [] | Some ps -> ps)}
| "[" ps:(!(Util.list0)[parse]) "]" {Array ps} | "[" ps:(!(Util.list0)[parse]) "]" {Array ps}
| "{" ps:(!(Util.list0)[parse]) "}" {match ps with
| [] -> UnBoxed
| _ -> List.fold_right (fun x acc -> Sexp ("cons", [x; acc])) ps UnBoxed
}
| x:LIDENT y:(-"@" parse)? {match y with None -> Named (x, Wildcard) | Some y -> Named (x, y)} | x:LIDENT y:(-"@" parse)? {match y with None -> Named (x, Wildcard) | Some y -> Named (x, y)}
| c:DECIMAL {Const c} | c:DECIMAL {Const c}
| s:STRING {String (String.sub s 1 (String.length s - 2))} | s:STRING {String (String.sub s 1 (String.length s - 2))}
@ -318,6 +351,7 @@ module Stmt =
| "#" %"string" {StringTag} | "#" %"string" {StringTag}
| "#" %"sexp" {SexpTag} | "#" %"sexp" {SexpTag}
| "#" %"array" {ArrayTag} | "#" %"array" {ArrayTag}
| -"(" parse -")"
) )
let vars p = transform(t) (fun f -> object inherit [string list, _] @t[foldl] f method c_Named s _ name p = name :: f s p end) [] p let vars p = transform(t) (fun f -> object inherit [string list, _] @t[foldl] f method c_Named s _ name p = name :: f s p end) [] p