Some highlights on what you can do with MBase:
Introducing an infix arithmetics syntax:
(define p.ident0 (p.alpha ((p.alpha | p.digit | (% ".:#$&!|@_")) *))) (bnf-parser ((expr parse-infix-arith)) (expr ((term:l MINUS expr:r) `(- ,l ,r) ) ((term:l OP1:o expr:r) `(,o ,l ,r) ) ((term) $0)) (term ((fact:l OP2:o term:r) `(,o ,l ,r)) ((fact) $0)) (iargs ((var:a COMMA iargs:b) (cons a b)) ((var:a) (list a))) (fact ((fun LB iargs:al RB TO expr:body) `(lambda ,al ,body)) ((LB expr:fn RB LB args:fa RB) `(,fn ,@fa)) ((var:fn LB args:fa RB) `(,fn ,@fa)) ((LB OP1:o RB) o) ((LB OP2:o RB) o) ((LB expr:x RB) x) ((int) $0) ((MINUS fact:e) `(- 0 ,e)) ((var) $0)) (args ((expr:a COMMA args:b) (cons a b)) ((expr) (list $0))) ) (make-simple-lexer arith-lexer (ident-or-keyword (p.ident0 |(("[" ((! "]")*) "]") -> (M@ cdr cuttail))) var) (keywords fun) (simple-tokens "->" TO "-" MINUS "," COMMA "(" LB ")" RB "{" LB "}" RB ) (regexp-tokens (("+" | "%") -> list->symbol) OP1 (("*" | "/") -> list->symbol) OP2 p.integer.p int) (ignore p.whitespace)) (define arith (fun (str) (lex-and-parse arith-lexer parse-infix-arith str))) (macro Infix arg (if (string? (car arg)) (arith (car arg)) (arith (to-string arg)))) (macro # arg `(Infix ,@arg))
Using this syntax:
(formap (x 0 100) (# x * (x + 1) / 2))
Adding the basic list comprehensions support to the language:
(function lch:tknize ( right )
(foreach-map (r right)
(cond
((symbol? r)
(case r
((<- & |) `(,r))
(else `(VAR ,r))))
(else `(OTHER ,r)))))
(bnf-parser
((comprexpr lch:parse-compr))
(comprexpr
((expr:e | rightexpr:r) `(lch:list-comprehension ,e (generators ,@r))))
(expr
((VAR) $0)
((OTHER) $0))
(rightexpr
((rightsome:l | rightexpr:r) (cons l r))
((rightsome) (list $0)))
(rightgena
((expr:v <- expr:e) `(<- ,v ,e)))
(rightsome
((rightgena:l & rightexprs:r) `(with ,l ,@r))
((rightgena) $0))
(rightexprs
((expr:l & rightexprs:r) (cons l r))
((expr) (wrap $0)))
)
(function lch:parse ( expr )
(lch:parse-compr (lch:tknize expr)))
(macro lch:list-comprehension ( inner-expr generators )
(let loop (( v (cdr generators )))
(p:match v
(() inner-expr)
(((<- $vr $e) . $cdrv)
(let ((nvr (if (list? vr) (gensym) vr)))
`(,(if (null? cdrv) 'foreach-map 'foreach-mappend) (,nvr ,e)
,(if (list? vr) `(format ,nvr ,vr ,(loop cdrv)) (loop cdrv)))))
(((with ($_ $vr $e) . $qery) . $cdrv)
`(,(if (null? cdrv) 'foreach-map-filter 'foreach-mappend-filter)
(,vr ,e) (and ,@qery)
,(loop cdrv))))))
(macro <L> rest
(lch:parse rest))
Please send your feedback to info@meta-alternative.net