-
epiqsは、プログラミング言語である。主に、Lisp系言語に影響を受けている。
-
Lispのコンスセルをそのまま書き下すような文法であり、この言語ではコンスセルをpiqと呼んでいる。
-
piqではcarやcdrにあたるものをそれぞれpとqと呼び、
またpiqはotagと呼ばれるいわば型情報を一つだけ持つことができる。 -
otagはpiq作成時に埋め込まれた情報であり、変更不可である。
-
otag付のpiqをepiq(=embedded tagged piq)と呼ぶ。
-
piqで構成された式を、A式(A-Expression)と呼ぶ。
(Otag p q)
が基本の形。
タグは大文字または記号から始め、シンボルは小文字から始める。
+------+-----+-----+
| Otag | P | Q |
+------+-----+-----+
grammar epiqs;
efile: epiq* EOF;
elist: '[' epiqs ']';
etuple: '{' epiqs '}';
epiqs: (epiq WS+)*;
epiq : ('|' tag WS+ epiq WS+ epiq)
| ('\'' tag WS+ epiq)
| ('^' tag? WS+ epiq WS+ epiq)
| '^{' epiq '}'
| '^[' epiq ']'
tag : TAGHEAD ~(WS*)
literal : INT | STRING | NAME;
TAGHEAD :
| ':'
| '%' | '#' | '@' | '.'
| '\' | '!' | '$' | '?'
| '='
| '/'
| '&' | '~'
| '+' | '-' | '*' | '/' | '`' | '<' | '>'
| [A-Z]
INT : ('0'|[1-9][0-9]*);
STRING : '"' ( ~'"' | '\\' '"' )* '"' ;
NAME : [a-z]
('a'..'z' | 'A'..'Z' | '0'..'9'
| '&' | '~'
| '%' | '#' | '$' | '='
| '+' | '-' | '*' | '/'
| '<' | '>'])+
WS : [ \n\r\t] ;
- ひとまず中置記法だけを書いている
{
~}
と[
~]
関連に関しては、省略形だけを書いている,
はまだ組み込んでいない
- 1文字リテラルとディスパッチャに含まれる記号は使えない
:
は中置記法があるのでだめ- 環境操作タグのうち、
%
と#
は使える。
@
もいいが前置では使えるので紛らわしいのでやめる
.
は完全に中置記法で使う想定なのでだめ !
は後置で使うのでだめ、?
も三項演算子やるかもなので置いておく$
と=
はOK- 余っている文字のうち、backquote 以外の
&
~
+
-
*
/
<
>
は許可
<
>
は少し怖いがやってみる - backquoteとbackslashはいけるはずだが怖いのでやめる
種類 | 数 | 具体例 |
---|---|---|
literal | 1 | ; |
parens | 4 | [ ] { } |
dispatcher | 5 | ( ) ' ^ , |
tag | 13 | : % # @ . \ ! $ ? = / |
matching | 2 | = _ |
unused | 7 | & ~ + - * / < > backquote |
合計 | 32 |
正規表現 | 説明 |
---|---|
数値 | ([1-9][0-9]*)|0かな。 |
シンボル | [a-z|A-z][a-z|A-z|0-9|+-*/]+ですね。 |
文字列 | " ~ " |
de bruijn index | .[0-9]* . の後に数値が続くと、de bruijn indexとみなす |
記号 | 説明 |
---|---|
; |
Unit |
^N |
nil |
^T |
true |
^F |
false |
記号 | 説明 |
---|---|
( ~ ) |
piq(基本形) |
| | piq(p,qを指定) |
' |
piq(pのみを指定) |
^ |
metadata 基本的には必ず2つ引数を取る |
, |
埋め込み 後に続くlistの[]を省略して書ける |
記号 | 説明 | 単独 |
---|---|---|
: |
cons | 中置記法でcons |
記号 | 説明 | 単独 |
---|---|---|
{ ~ } |
省略形 現在は^*{ ~ } と同じ |
|
^*{ ~ } |
tuple | |
^+{ ~ } |
enum | |
^#{ ~ } |
hash | |
[ ~ ] |
省略形 現在は^:[ ~ ] と同じ |
|
^:[ ~ ] |
list | |
^-[ ~ ] |
vector |
記号 | 説明 | 単独 |
---|---|---|
% |
environment | ナシ |
# |
bind | ナシ |
@ |
resolve | 前置記法でresolve |
. |
access | 中置記法でもいける(間にWSは許されない |
記号 | 説明 | 単独 |
---|---|---|
\ |
block | ナシ |
> |
eval | ナシ |
! |
apply | 中置記法でapply (pとの間にWSは許されない |
$ |
symbol | ナシ |
? |
condition | ナシ(中置記法は微妙) |
記号 | 説明 | 単独 |
---|---|---|
= |
equal | 色々な比較に使いたい 中置記法は迷ったがナシ |
^_( ~ ) |
pattern | 中に_ がplaceholderで使われるので、それだけでpatternと判別できればこれは不要 |
記号 | 説明 | 単独 |
---|---|---|
/ |
path? | ファイルパス関連で使いたい |
記号 | 説明 |
---|---|
|| ~ || | comment(複数行) |
!? |
exception |
記号 | 説明 |
---|---|
'' |
comment(単一行) |
!. |
yield (不要かも |
!< |
dispatch |
記号 | 説明 |
---|---|
^{ ~ } |
現在は^!{ ~ } と同じ |
^[ ~ ] |
現在は^.[ ~ ] と同じ |
^!{ ~ } |
中身を深さ優先で再帰的に評価 |
^.[ ~ ] |
quasiquote 実行を止める |
記号 | 説明 |
---|---|
!& |
parallel |
.> |
|
.>s |
format |
- ASTをたどるQuery(XPathみたいになるよね)
- モジュールの具体的な仕様
Plus, // + plus
Hphn, // - hyphen-minus
Star, // * asterisk
Slsh, // / slash
Tild, // ~ tilde
Bkqt, // ` back quote
Less, // < less than
(使用済みになりました) Grtr, // > greater than
マクロは普通の関数と同様に作成する。
- 実行には
>>>>
タグか^{
~}
(これは^!{
~}
の略記)を使う。 - quasiquoteには
^[
~]
(これは^.[
~]
の略記)を使う。
例として、|!! symbol [args]
というタグがきたら、
|! @symbol [args]
に変更する関数を書いてみる。
|# .double-bang
|\ '% (piq) [
|>>>> "実行用マクロを定義する"
|? (= ^_(!! _) .piq)
|: ^[ |! (@ ^{ piq.p }) ^{ piq.q } ]
piq
]
|Defn |Accs Unit double-bang
|Lmbd 'Envn 'Cons piq 'Cons
|>>>> "実行用マクロを定義する"
|Ifvl (Eql_ (!! _) |Accs Unit piq)
|Cons 'Quot |Appl (Rslv |Eval |Accs p piq) (Eval |Accs q piq)
piq
次に、このマクロを適用したいコードブロックの環境内で、それらを紐付ける。
あまりお得になっていない気がするが、まあしかたない。
|\ |% [a b], macro_function:@double-bang
[ (!! plus [(!! plus [3 4]) (!! plus [5 6])]) ]
ちなみに、マクロ定義時に、引数で与えられたpiqから、
.pや.qを使えば、子を辿ることは簡単だが、親や兄弟は辿れない。
そのための何か文法は欲しい気はするが、親に影響を与えられてもいいんだろうか。
tarai関数
|> ; ^> -1 [
|# tak |\ |% ; [x y z] ^> -1 [
|? |> ; |! |> ; |@ ; ltoreq [|> ; |@ ; x |> ; |@ ; y]
|: |> ; |@ ; y
|> ; |! |> ; |@ ; tak [
|> ; |! |> ; |@ ; tak [|> ; |! |> ; |@ ; decr [|> ; |@ ; x] |> ; |@ ; y |> ; |@ ; z]
|> ; |! |> ; |@ ; tak [|> ; |! |> ; |@ ; decr [|> ; |@ ; y] |> ; |@ ; z |> ; |@ ; x]
|> ; |! |> ; |@ ; tak [|> ; |! |> ; |@ ; decr [|> ; |@ ; z] |> ; |@ ; x |> ; |@ ; y]
]
]
|! |> ; |@ ; tak [12 6 0]
]
tarai関数(with syntax sugar1, 実装中)
|>>>> [
|# tak |\ '% [x y z] ^>> [
|? '> |! '> @ltoreq ['> @x '> @y]
|: '> @y
'> |! '> @tak [
'> |! '> @tak ['> |! '> @decr ['> @x] '> @y '> @z]
'> |! '> @tak ['> |! '> @decr ['> @y] '> @z '> @x]
'> |! '> @tak ['> |! '> @decr ['> @z] '> @x '> @y]
]
]
|! '> @tak [12 6 0]
]
tarai関数(with syntax sugar2, 草案)
^>>>> [
|# tak |\ '% [x y z] ^>> [
|? @ltoreq!, @x, @y
|: @y
@tak! [
@tak!, @decr! [@x], @y, @z
@tak!, @decr! [@y], @z, @x
@tak!, @decr! [@z], @x, @y
]
]
@tak!, 12, 6, 0
]
fibonacci数
|> ; ^> -1 [
|# fib |\ |% ; [n] ^> -1 [
|? |> ; |! |> ; |@ ; eq [|> ; |@ ; n 0]
|: 0
|> ; |? |> ; |! |> ; |@ ; eq [|> ; |@ ; n 1]
|: 1
|> ; |! |> ; |@ ; plus [
|> ; |! |> ; |@ ; fib [|> ; |! |> ; |@ ; minus [|> ; |@ ; n 2]]
|> ; |! |> ; |@ ; fib [|> ; |! |> ; |@ ; minus [|> ; |@ ; n 1]]
]
]
|! |> ; |@ ; fib [30]
]
fibonacci数(with syntax sugar1, 実装中)
|>>>> [
|# fib |\ '% [n] ^>> [
|? '> |! '> @eq ['> @n 0]
|: 0
'> |? '> |! '> @eq ['> @n 1]
|: 1
'> |! '> @plus [
'> |! '> @fib ['> |! '> @minus ['> @n 2]]
'> |! '> @fib ['> |! '> @minus ['> @n 1]]
]
]
|! '> @fib [30]
]
fibonacci数(with syntax sugar2, 草案)
^>>>> [
|# fib |\ '% [n] ^>> [
|? @eq!, @n, 0
|: 0
|? @eq!, @n, 1
|: 1
@plus! [
@fib!, @minus! [@n 2]
@fib!, @minus! [@n 1]
]
]
@fib!, 30
]
'!?
|:
|# f @open! "myfile.txt"
|# s @readline! f
|# i @int! [@s.strip!]
|:
|: [ OSError : (\ '.> '.>s ["OS error: {0}" .1])
ValueError: (\ '.> "Could not convert data to an integer.")
T : |\ ['.> ["Unexpected error:" @sys.exc_info!.0] !?!] ]
'.> [arg "has" @f.readlines!.size "lines"]
@f.close!
'Html
'Head
'Title "onclick test"
'Meta, http-equiv:"Content-Type", content:"text/html", charset:"utf-8"
'Meta, name:"viewport", content:{width:divice-width initial-scale:1.0 minimum-scale:1.0 maximum-scale:1.0 user-scalable:no}
^!~ {
(# leftpx 0)
|# touch |\ '% ; [
|# leftpx (+ .leftpx 10)
(# (Selector#migi).style.left "{.leftpx}px")
]
|# reset |\ '% ; [
(# leftpx 0)
(# (Selector#migi).style.left "{.leftpx}px")
]
}
'Style [
".yaji":{font-size:"20px"}
".btn":{font-size:"20px" width:"200px" height:"50px" text-align:"center" margin-top:"20px"}
]
)
|Body, bgcolor:"#FFFFFF", text:"#000000" [
|Div#migi.yaji, style:{position:absolute left:'0px'} "■"
'Div, style:{clear:both}
|Div, style:{position:absolute top:'50px'} [
|Button.btn, onclick:(! @touch) "onclick"
|Button.btn, ontouchstart:(! @touch) "ontouchstart"
|Button.btn, ontouchstart:(! @reset) "reset"
]
(FoldTagR +, 0, [1 2 3 4 5 6])
(FoldTagR :, ;, [1 2 3 4 5 6])
|# touch
|\ '% ;
[ |# leftpx (+ .leftpx 10)
(# (Selector#migi).style.left "{.leftpx}px")]
|Defn touch:[],
|# leftpx (+ .leftpx 10),
(# (Selector#migi).style.left "{.leftpx}px")
|Defn sum:[a b], (+ .a .b)
|-> (+ .0 .1)
表記 | 対応する表現 | 説明 |
---|---|---|
Unit |
; |
unit |
None |
N |
nil null |
Tval |
T |
true |
Fval |
F |
false |
Int8(i64) |
21 745 |
8byte integer |
Text(String) |
"wowow" |
string |
Name(String) |
map index |
symbol |
Plhd |
_ |
placeholder patternで使う |
表記 | 対応する表現 | 説明 |
---|---|---|
Tpiq{_tag, pval, qval} |
(_tag pval qval) |
tag assignable cons |
Lpiq{pval, qval} |
(:a b) '|: a b' ': a a:b |
linked-list(normal cons cell) |
Bind{smbl, valu} |
(# one 1) |
bind |
Accs{trgt, kynm} |
(. piq q) obj.attr |
access |
Lmbd{envn, body} |
'\ .0 (\ '% [i] @incl!, .i) |
function piq block |
Same{val1, val2} |
(= money happiness) |
equal |
Appl{func, args} |
(! @p, "OMG") @p!, "Good" |
apply |
Cond{cond, rslt} |
(? ^T "true":"false") |
if or cond |
表記 | 対応する表現 | 説明 |
---|---|---|
Envn{_, prms} |
(% [i j] ^{}) |
environment |
Rslv{_, smbl} |
'@ sym @func |
resolve symbol |
Eval{_, qexp} |
^{ @go-a-head! } |
exec eval |
表記 | 対応する表現 | 説明 |
---|---|---|
Tupl{lpiq, rest} |
(& a '&b) {a:1 b:2} |
tuple |
Enum{data, _} |
(~ LIVE '~DIE) ^~{N E W S} |
enum |
表記 | 対応する表現 | 説明 |
---|---|---|
Quot{qexp, _} |
^[ a b c ] |
quote |
- walkを通していない部分をチェック
- READMEにcond抜けてる
- Same(これもまずは数値だけ、ただしこれはotagではなく関数では?)
- 文字列
- dispatcherの追加('と|だが、どちらがどちらかは迷っている)
- 中置記法(Lpiq, Accs, Rslv, Appl) 優先順位も決める必要がある
- N(ただ、すぐできるし、使い道が出た時で良いかも)
- プリミティブな数値の演算(加減乗除/ビット演算 shift, rotate)
- マクロをキックする(定義はできるようになったが、それをキックするタイミングを決めていない)
- パターンマッチ(これは難しそう)
- Tupl, Enum(仕様がよくわかっていない)
- Vector(Rustのarrayを使うことになる)
- エラー処理
- 配列というかイテレータ的な処理はなるべくタグで組み込みたいけれど、どうするのか
- 文字列関数