From 8281e037a43ee252ca43699b991b3e28bfb82d13 Mon Sep 17 00:00:00 2001 From: Fedor Isakov Date: Thu, 23 Aug 2018 16:37:42 +0200 Subject: [PATCH] Fix the wording of docs. More docs content. Drop obsolete stuff. --- docs/content/allpages.md | 4 +- docs/content/evaluating.md | 35 +++++---- docs/content/example-logic.md | 2 +- docs/content/example-typechecking.md | 53 +------------ docs/content/img/errorDialog.png | Bin 871 -> 0 bytes docs/content/img/eval-aspect-400.png | Bin 0 -> 35376 bytes docs/content/img/language-recoverct-700.png | Bin 0 -> 27794 bytes docs/content/img/mps-logo.png | Bin 5569 -> 0 bytes docs/content/intro.md | 12 +-- docs/content/language.md | 72 ++++++++++-------- docs/content/overview.md | 34 ++++----- docs/content/todo/todo-evaluating.md | 6 +- .../content/todo/todo-example-typechecking.md | 46 +++++++++++ docs/content/todo/todo-language.md | 12 ++- 14 files changed, 145 insertions(+), 131 deletions(-) delete mode 100644 docs/content/img/errorDialog.png create mode 100644 docs/content/img/eval-aspect-400.png create mode 100644 docs/content/img/language-recoverct-700.png delete mode 100644 docs/content/img/mps-logo.png create mode 100644 docs/content/todo/todo-example-typechecking.md diff --git a/docs/content/allpages.md b/docs/content/allpages.md index b6eccf0e..266dfd5f 100644 --- a/docs/content/allpages.md +++ b/docs/content/allpages.md @@ -3,6 +3,6 @@ layout: print menu: false --- -Revision: 0.5.0 +Type inference and type checking is a problematic area for language authors — users of JetBrains MPS, because of inherent intricacies of the problem and sometimes inadequate support from the framework. -Date: Aug 23, 2018 +*Code Rules* is a new technology that brings logic programming in the form of constraints processing as a vehicle for implementing type inference. diff --git a/docs/content/evaluating.md b/docs/content/evaluating.md index 3dd7d86f..503f0024 100644 --- a/docs/content/evaluating.md +++ b/docs/content/evaluating.md @@ -6,38 +6,43 @@ weight: 40 # Evaluating Code Rules -***Two stage process*** +The process of evaluating code rules consists of two stages: -## Aspects +1. Collecting handlers and applying rules. +2. Processing constraint productions collected in the first stage. -***Aspects*** +Stage one is executed in the background in a read action, and is expected to finish quickly. Stage two is executed on a worker thread and does not require reads or writes. After the second stage is finished there is a short write action which «publishes» collected types. -## Applying rule templates +### Applying rule templates -The first stage of evaluating code rules is applying handlers. Handlers are collected from corresponding aspects of all languages imported into the model. +The first stage of evaluating code rules begins with collecting handlers. Handlers are collected from corresponding aspects of all languages imported into the model. In addition to that, all extended languages are also included into the scope. -As rules are applied to source model nodes, they produce constraint productions generated from templates. The order of productions is kept as defined by handlers, with handlers from extension languages having higher priority. +All handlers collected in the previous step are sorted, so that the ones coming from extensions appear earlier. This sorting order ensures that when productions are selected to match an active constraint, with the productions coming from extensions having higher priority. -As well as generating constraint productions, the rules are allowed to report messages to be displayed at source locations. +After the relevant handlers are collected, the source model is traversed from the specified location, and the applicable rules are evaluated. As rules are applied to source model nodes, they produce constraint productions generated from templates. As well as generating constraint productions, the rules are allowed to report messages to be displayed at source locations. -Generated productions constitute the constraints program, which is then executed. +Generated constraint productions constitute the constraints program, which is then executed in the next stage. -## Running constraints program +### Running constraints program -In the second stage the constraints program is run. To begin execution, a query is selected, which contains the list of constraints to be activated. Query can be viewed as a regular production, which is triggered unconditionally right after all headless productions (marked as «on start») have fired. +In the second stage the constraints program is executed. -***Order of productions firing*** +To begin execution, a *query* is selected, which contains the list of constraints to be activated. Query can be viewed as a regular production, which is triggered unconditionally, but no earlier than all headless productions (marked as «on start») have fired. + +There is a fixed order in which productions are fired on start of program execution. First, all «on start» productions are triggered. All constraints activated by these productions are processed normally, and after there are no more productions to be triggered, the query is fired. Order of productions fired: - - on start - - query +1. «on start» +2. productions in a query -While constraints program is run, it is allowed to report feedback, such as assign calculated types or report problems, using special predicates. +While constraints program is run, it is allowed to report feedback, such as assign calculated types or report problems, using special constructs, that are available as predicates in the body of production. ***Feedback predicates example*** Failures during evaluation are caught with the help of alternative body branches, where those are provided. An uncaught failure terminates program execution and is reported to the user. -## Activation trace view +***Alternative body example*** + +### Activation trace view ***Activation trace view*** diff --git a/docs/content/example-logic.md b/docs/content/example-logic.md index 0c765bbe..22db393f 100644 --- a/docs/content/example-logic.md +++ b/docs/content/example-logic.md @@ -35,4 +35,4 @@ The rule’s body activates `valid()` constraint, therefore only reasonings that Finally, if the proof’s goal is marked valid, it is assigned «Ok» type, otherwise it is marked with error. -[^inlog]: Stanford Introduction to Logic http://logic.stanford.edu/intrologic/homepage/index.html +[^inlog]: Stanford Introduction to Logic [http://logic.stanford.edu/intrologic/homepage/index.html](http://logic.stanford.edu/intrologic/homepage/index.html) diff --git a/docs/content/example-typechecking.md b/docs/content/example-typechecking.md index 62b02ea3..5c9c8e57 100644 --- a/docs/content/example-typechecking.md +++ b/docs/content/example-typechecking.md @@ -57,7 +57,7 @@ Whereas `assignment` does something more: it ensures that the actual type on the ![](img/ex-typecheck-assignment-700.png) _(typechecking of assignment expression)_ -## Type Relations +### Type Relations Several kinds of relations on types are defined, surveyed in the following table. @@ -69,7 +69,7 @@ Several kinds of relations on types are defined, surveyed in the following table | subclassing | `promote()` | subtyping among classifier types | | containment | `containedIn()` | type parameter containment | -### Conversion +#### Conversion Constraint `convertsTo()` ensures that a type can be converted to another type, that is a type A can be used instead of type B. To test if a type is acceptable in certain locations, including those that allow any type, the constraint `compatibleWith()` is used, which delegates to `convertsTo()`. @@ -81,7 +81,7 @@ In its turn, `convertsTo()` delegates to either `primSubtype()`, which is respon ![](img/ex-typecheck-convertscls-500.png) _(`convertsTo()` delegates to `promote()` for classifier type)_ -### Subclassing +#### Subclassing Resolution of `promote()` constraint, which represents subtyping among classifier types, is implemented around a simple idea of representing all subclass paths the root (Object) to a classifier as a set of lists. This representation deliberately ignores the class parameters. As a first step, the shortest path from supertype’s classifier to subtype’s one is selected. This path is then reversed and represented as a dataform list. This makes it possible to pattern-match on this list, since it is nothing more than a cons list represented as a dataform. @@ -98,50 +98,3 @@ Suppose we need to decide if `Long <: Serializable`, that is if `Long` is a subt - -- types - - term table for types - - classifier type - - type var type - - capture type - - array/vararity type - - upper/lower bound type - - wildcard type - - primitive type: int, bool, etc. - - void and null - - macro table - - classifier type - - type var type - - bounds - - parameterised types - - types with value -- Query - - Typecheck - - checkall, recoverall - - ConvertsTo - - convertsTo() -- Typechecking - - Constant values - - string - - integer, long, char, … - - expression - - dotexpression, dot operation - - method call - - **type parameter substitutions** - - equals/assignment/+assignment - - - - ??? - - method declaration - - type relations - - boxing - - capture - - coerce - - conversion - - primitive subtyping - - subclassing/promote - - type parameter - - containment, hasbound - - type annotations - - classifier type - - type parameters: type var, bound type, wildcard - - diff --git a/docs/content/img/errorDialog.png b/docs/content/img/errorDialog.png deleted file mode 100644 index d4b8d2bdb681c17ddef638e5123d1b084930b287..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 871 zcmV-t1DO1YP)R<3}g^W2`&QY#Km$lPHNyRVTKDk%k#k7Y6X9P2LwkPur@jf zYp(_%Fw{e@;XP+XeyWifrg1C-=LtbRu-t8@gV8~?ATbz=Im|?mmBo;O3#_)VWV1kU z*a4vzj}3u2?xqTEBE~dz88}DS!bDF?HH1d`(z5aPB_tvnu)i6G@c3)hI8RFrH-Va& zA_Hf5&FPa5b*mCzT><{v3o4qisKrdovN2Q*;F}BcmTT~HpbG*|9;kBkrxlA@sL4!N z)C`#UQuDRhNK&UJM}MMtU%M@JiJH?H$mUP4INF5lM}H*;KiG}x%1N1p>~sdO!-2c8 z43r+bkeJU62k|&1E_rq3pf)qmo6f)_oql^A_#ZY4+4=ez_P4hvJKv^t<@oHi+`z|l z2C$!l)NX~mno5nce-*=n;B5j8K8|vCPDH&n~>1hGl)9BQ$lZsb>+y1 z24boPq`P$>wblz!NbldCo}?&)_jToC z=u5b4Eun#WSZQsb_*$xT#iO>?ONg5Za8>1l_jcJI0kyT3A#Fr+#kt^VEEN(MeF}-q z2qd;55Ey%|D+jf;8d0(pFI5+S$6Bn(-g+q62@@OZ!g$n7X~h|8A0rE$g`2ssTwe&w z4MnQ#dfiC_alfP)i(05D`WW%g@hsg1m0kgNU7;${BRiReHQI>e{!YzU)MA5w5q*wL zY|}tDBu>j!aM#{A5er1a$cBWI!yD6l$z@W%d|0X}Fb1jl{NaxuQ$p zD!)!e^?tJ%!2=4D4gsC(~vnh5jOKV_N1OM&m_%{XHlQ4>gIMo0E002ovPDHLkV1oaNi;DmN diff --git a/docs/content/img/eval-aspect-400.png b/docs/content/img/eval-aspect-400.png new file mode 100644 index 0000000000000000000000000000000000000000..76bcf8f63b772fa8eec3c6a807a4d87a829874d0 GIT binary patch literal 35376 zcmXtAW02@i!6(GWnAy)zj0{Nu+|DI4l$v z6aWAKtfYj95&!^T!oTwt2%vxapDDh|e+NKkC2=8u+F6|Qe*vU}gr+k902=9k8=#~T z$sGWI0Dz>3po$0Jl`pstviRdmg}Zbr?L?2dPCabt>y9^l0hkbE2pU9)06`!?!RwCj zZ7F(|(NZj9tE0VBnyG4)^y`ddtpO5&=kG+Cg@3Ed#%4~A?~9$CyWOiMPE=t8s}C9w zz*Z!Cgi7$9S=_0BRtAJiz^2biGtPLBJ3(2#}iviw0o>k%8!* ze^9`R!8dFD0c3<4CH<^#E&E?j@bHyer*BqKjS>ySdZK{eaDjxpM4zj-$f(Kq>ud{Z zQ=^J6{6e0<2o&w)QqCK?^bDZk^DAOST&Gph_7RaFJe0y%h?$}-HjQ|hQ9$m z$$Vfb7H9o>W3?mS#|}QZ0zi14&ZlN_oQ7Me==$IFkul;jrE^IpGp3^bQT?}scfElE zuwK5xesAz2#*46Ehh3rh<$Ajg?vizDJxO@+NfDFO7%E&T550W1P+_|wL=R-7y77K0 z2bo`F!370gfe)~k?*(sIfvn(nJ3?iOk2pL)!a5WzR2tIs!pAZ9D?XQoVj*!7#my(IkLyBDJDR7#FxS^;72Az4 z{J$Md`7*1en-L?>ryT1@2rAy^!>P1g@~Kg-KIrj~%Ds4u<=7L|T?~gSC$Z8ud~^(0 zj(WCT^jYk?@tWOcO9jVeVx#1;_sE8u@JqC~L&Er0V zg`9K42lj)5unq4)9_G62 z1bp;1T1NeJoTYl};>mHo>R+RDJbE+}nrdor(d0|-vUPQHa>DI-Y!%PHWU7<9-y!N$(FMQYuD`CNpO{d6-+hBb$n$rlMJaSW>w4_X7qCv1 z!D8|YRqOa%4DASibhob^g1NlP&NyH{! zEw8E9Zck23(bH1)HeYa41--GJmxwONMl*CR{aY8Q9!OS;8-Aa3@>&ta8TgqXf}Jki zx^AHTIMSsFhy#obD#quAK4R1YP80kHfZ$T;9H8Zm0=T zvIZEU=mYr;h4Q{DUzoA1R5{Xxp4(o;p$55hlwreWyq=wWWjH8D_%k*w)8_H{7|7Q+ z92P)796eTSLvUXD#^EBdo>had`~j{H9Y*8FmHS=$gN*~?aKElc)XvL}6$4d4^Y2EY zyEI}2?tq08Q{44VVn$ZsDt5~!E!d}62PFqt&cB}o5|hWoQ`%&DSF1hlx4pny?JgjS z!OwvV_f?v9vvm3~`0b9TxiF#o_uuB7O0YtTJ3U?$=R1&+nrz)nQz=kMBB-LT()CZw zr*2j!fZ)8~vjOrDZZ9t$qWN?wwq@l7lpASYB6q@u8fVRHU-}WXX{3A>M|t z_VaD0A+T##swIvIWZk*VX6B}->FCg)LIL-4$XqT9nF$Gf$Mo7Ailb?r z&ih*pgS(!vSV}Y=cBny{`1S_N95( z{qi4nQYg;Br**97a(@E)m#dd+a5-Vfbijfp^jhBMYbskOqpz0^WB2X34eTtIMr~*5 zcf~qAS)6skQ%xJqhM)tw7-3?kn~?vJ2_V(I9yLzuzj>zoaT;Zkkn*<$Z%fuxb9S0MZu_n4 zYmZ?r5PtNSXn{kAktU77`U&EfaE^74FkV-%rL6ze$2)$Z{K_n$;)nY?GI?FE>)`_F zQ#qgSAuS9$L53ujQzHLq+M3Ewes~5DC-`p?f$YvX! zE`7p>aydjgl_5!#h284fuQ;_TRk zapHYJH1zm8eBRG-DvFS~)UC4t!V)M>s_u<~z6Nr@)gywk^SfSUb87}p*2VvWMj*gw z^=Xs&YYo0Ap=zhTHx@YKgnOB_e3XixjYL*gaYsBp+go1X_~zLImsj|^mZJhjp7<>< zxJ4)Acz642RrR9%B)4Ge&0^}!MxO+LEuPc>V!J+vzD}2wPROC|_Y?O}h()XSK>mjn z%sD%)bK^1OI~`sgp4lC5#iXCTQhR}~2ir9(BR0C6+5HVKZ|}Faccux6wB8}9lDkC! zRa6t7l^WPck%#-o*B6Ht!UuDl{_Zz&_n+Z`{jDA!pB~=7C>wW>yAvv`gBQ34_K?U6 z*K_l}kQRCSMORp^yJ+z@-nOotYr+%%2v)y-1OS|gswTqn9SvQp1WCc)hb-233OV^i zOGiIKLK~5+oG-E-2@@7fND?oRB{Ml6jIoL|)_9$J8qeR3s)D%cuRl=mx8o5CZnYtcoHq<+#zgn23fi~_iRoc#qC2%Jb*O!4$u}jLUfG#5R^6T?ED~ImJ#Bz zuC&9)603(Pe$tQ`23e$#Q&@Tu$a&-^}Ok zQQS`HaR0_wjr9sXzA4%mW?+buba{$~fO02AfCP6k5flE{Dpm}HaCCUK+2HA2|1^$Q zeS_@L*ubJtJy@Kwhr8q7a$b|)jur&&(~gA@&`@g&)2gfz|0|5JK&~*WWsoZLwn#6^ zJ|DBp?0r~^*Gr8*@=8UfpdI$cMSbb-rbT%C`rMu6C#u_-_T+fJ>8~I6+wgyL=G4kY z4FSb=lbh6Q95B83as88mQ7Ki+)jzsyg?s75V2Ce~vmnPul|$yEue z<p_H4w{!{Z{oC0fxNI|MBp=Sb=AfVE@)swd-n#|6m0GLIXDS znW_H2i@(?))nJ#uS*49sR{zoCUE_Mao#@Q>m1cc+9qaVVNBwOY%lr6vTwb)tBirYY zZGTtWnv|x0Rhj7S6{EU2W^L2`mdlmu{+9BGUi3~mG;%UpkFgr%HSz)uI8#VST3T56y)ODUkXnG54-V>iiozK^(!Yj@1AiaNzB zJwO3hL54B^s}em%gR;L_mHxrq@5|3CSg&kl)%1$Va#{i4740A9qIpWZaUUBwxvXE< z)rgfWe1mrt_bmafD*tkVSjmo-so}b1aQIrhwr+<p`mokG(6!v~OW&r`h$r8TFkm~UxwO||YLGZKEU%=ubrc=qs0 z(k0l-_zURJ!8ZGYq(_usad=8k+@wD>E>37Dr^PAiR-n0t-`>rp3XlTSA3QgLLQYr+ z{PVUPvYBmmNLQ~nSCw3#06D3oJ!0l2^$kymg6l+g2TyO_@w@fc+t=wI>XG)WU`gf{ zQ-L{I(a=ry+a0<}fwn3GBoj2NP>Yu>QRMJ9J$_lRVGxtB_8Wzk8U!?iR5HGZk0cpG zuX~Hl_mUM_#8~sqvFM6kkDg`{A|ev`^m8&(%HqVA1^;>)5THEU`uQg7v{;R1tbwHN zube#o?$@J*Z>Oh|FT)(xjPvkU++-%i1GfBY0CM=&ibCL|*>I!3T+Qm-*2$POl<8+S@0 z7nyf9>d!AGr52hj0<)}7A?C>2==7sw#}v<6WvJ%E(I7&>w%XAIZ*HSUj1-KwW~ABi z$qmjilY_3Ff_w@P`3p4jqqS(Hr2V4XCK#e(=j&`0Krv zgY@mLH#!|R=4VBa62l0TXlvHGSGZ4NNie9AlpaVz-D^v_MG#iyH{;?j5gEGeyTBny zL4Z06Dg0hAP=PsLqrGP;Y=6Geg?ij{=%Ioxm1HiZ*vc`8Z4 z!L{=Gz-3l2KC>;E|2D4)3F zt0|hx^+;9KqEakB8ks}hCGyakss-K*ZRhE9yfE~+c|4UL1lkHr`1#I9IqmUDiXxuh zaKT^Z8bAMOQEq^IpUdO7MLGjYg=m+31~byw#LLM9C+eL1^B^UusMXsZBx2@z&Obed z$Lso~5~%`ADJp7Nm((Odv(t}A{H=SPyWQt?xU&?ZeqTe>P3r_BrX=#Ihf54BgC!c- zzBsh&99874rQ{^#C8jml^u&Iz1AZz-D7)DLQS^1YD%q>=Zykdg*asg7X7?7aSgQ0# zfr!4WGb|pTJH}cVhxcYmcGEruJ>{qhkst|3A8~~AYz(w1+jG5ra^P>%-9(^Nq~snh zla+)%I2@Cm#xFQz*F8x#2cIPI0`c<068PE{r(A04sb!2rYw?~f=|RZY(LC>b<3Ij;N+2yipz@i#v|EjK2d75sMIgx@BoGsB zcbPvyxUK!|IJ;@k!f+L;sZ~v;+37Y7O@b(SNND(I--P0LN(vWn$|?Y#RK|Gr4t=8| zL3CI=1iWWTGIiPnb>I`UR}2|)%H?u{F0}S^VWX|5gx&#f&+5376C~^t7*sfb{MaCR z1_uunJ?cQKfybYl_ag3lh{}rO{d*5c2&R0Exh0dr%?=lSpUd-6@tZH*jM_;z5?t#*3y{@9B`NF84FH* zLh5;pQ_jSyP5m322{~7L9b+)4V46LXMZc_Yenv(4T{0DMP$usK2koDnbS;_S;Wx7x z?LAOG6@o9}23TAi4ixaS`X2Oth{0X&1r3m;orS3((!OpY_UBkBq6b)rr^jbElsl{L zEfQu>4Om1Blu%(=5vT>BS<{z@Ljz~AoKVZ3Z>Ibc3aR3R@%lsN)+*}udBZB`q8$kC zE+grjGZm-p+6=^Y=~#%!n6`Ohq{?^cf-s6bW0r9eq{l%UoZW@U@uNM&>1%i=3>K!V z8AWys*NY$^LoY8aFR|2iA*q5UogQ9`mF8$yWv%!ch%aiyH<@73V#sloMiOfN8_O_v z^Sesl3t+IR5pI+5gjx^g9H3HtS%E;Hj5zW{l;h(;B*@KJ?QH$RMM4{} zk+3a>q7+Wv1|=0Tnj|)-eUywP=L{4y$ZlKJ)=?YSsuvBUDsVrxa{#N=oXX zjK60SY$iCf5=IVS@fg?rrb1{nQgn&f>muFjUzJEk(;8~$TG_b>uDn_lXqV4q-hs{< zk8*|ufwOTwmk#x%j5XlDULbr+28{2t;Oy327YEy@&SEDp=dK6yJ5tDtO(P6!fQl^3 zj17*~$HsGWbJKbphG*{#ecR&t0F7e7vjc6;Cd`7%!PAt;Vey!(K_=BPyq-!o3_ohi z*_E3;1859X?s7O?tb|3IzDJ`S8MkF5N)~!Qf_LOq2qomCJ(7M&N%YCquw^Vtw=yP={bDU?&Sx*Vp`#N9JV{l#EKh^Xygch`lX$E50X`cQX|LQj>|$ts=B zM;7eiR@WE4($Npm!%TDi_45e{0QT@;Gg6jX@c5VUzd%5Fmh}!Eli9Xe%*RP{JKl{~ zvOGa$F1U=IQ=JnGVnF1H9nipW=^M2$8Rrcq@9`PRrzAYl-j8Gr!b=hB==b$gz&0=4 z-mk6a%xSuvpC0?sV*wnw5*hQO-6<>_A@v4cbL0I2$S%$YtD)|gDS&tMo;wEP&+l!Or z+$3RBcFz{0d#56`cS-_DiZRX|Pj0Y&0DP##@|5AQrbIro!0cxco}{RzSSbTTJ7V-s zLi8oDtHSs&Rczt}n3{W(6rpdywz#$^s)HNFJmpIjD;P$u$q$eei|(PTj<7PF__;|8Qy(at$|6$p73Tq zoL*b)_eo^3I`u9kD!Nk>;U#RCNO)s5>y5&NgQ?FxKJEVJZH~rcwcCD8Zk3l~W~+Fc z4F+57^mhD`e*EDg>02efNq3_|`sS;|&?2xO=8WuYx9e5QYiqy0i2nN1m+fc3pYWqR zvY#rb3dYCVySJPwDu z>6FdUkFKAHMY@;Uh3~ZCKom@i^QrPu|bhXM2elMn=2WL}KwKX{_?- z1&i_7NqP#JWs8gL(80BE@0YW#!#C1y&vzGLqu-x)Cr3voDJ#i}FJ;w%f{(@Sr?zuV zDOcb*`hF3ptT1V6*-3}W6sRC(aFt$-uXHEe<)e;~GBngy_F6pB^xjJXV$L>#^ zo;6zjV~@`lu~mWe_m4a_DBnYQyR(&)_jK;yaPca~Q5sAwiOZ%jq}ussKUo z0);@9JNTpiYF{G2RDl(tutfWQdz`^W=ZpCUXrZ7HuoiPcMAS)oYHszYO1s-Rtc6(h>OS3zhlmk!|)GjgNb(kxHjm z`=7@#9m>5JDk%Q@WBT&>wTAq48dnmaR7c>-X}4xjJnD6s_L_bn!F)NAU2Y?bAFo;VBxp3GFK{BgtIrSE5a}v_` z_Iks7UKv~N{R-%Strq9P1Nq9Q$0p?Dd~+y>qjA{j4|`T-1+xUX=r^MW^3?*aR z($w(aL>mJ9y|}0D%dNQ|w*+?`U{eb3kI9nY#(GMaGEAgy*I_=)CLHb7>NFWWS8Kv9 zWM!t05$odc=rY*aR7G{#>wP@z?5xP;5BVZFZ1kih*|Qd90Xp(VMe@2G+XcenY^Zr? zxINZO)kdj@BdFiI*}VQ-J^80=$_OL`#6RojNkWPieV`{s(;>{y8{_#&r^O{^sFM41 z41cJZLn>63hm+J8$JV5+ehimW=`q=FmM>+isr+C^k}}@n#k-o{1Me; z*-q#0SOQl{n+G~!r8g0 zU8hs3K*9^{@Z@lXO98?6n5JC7to{n)=+9U66zK?rr;&1>JESL#=vi`!I=#rTR5A=% zl}5T6q%7zt28P2^rnI>{Sutv(ZHF6=une&nJBFVEn9#(qCemXyWjyj-bF zqt8`;wW*w}en&zrO`$?DskF^AG$!|DT#l0i(uN7{TI^=8&~6%haY2l1Ult_Tfo6$6bdwg8@X!CyeQGe->3L4Q^U1Uoh^@@r1}- zaDOXC^yMD7u;b}d0#3x}xwZn-!q z#FW3mro$O?1}f`zZ=mC$izQ#FvU7|%7*ME?nZvrPuK)sMEiP7~nYAzwvrM4+r%Po< z;7T?ipG7P6tS)w%`W6QeNguY@f1K)LvGJ*Y${W!;GJPtSJ)>vGUD&bk$26pEk7B-Cw)^I#A3g#Ue05MhKH??2x^2Hnenw;J>`K z1XIx^VqiM0M{u~@``0}*uc;MLAt=*|De~f4Z*Ntg&O1@Dh_svWxST4v_XlM);S6dO z7Xl3AKH;Tc+>t>Q04fd~$GKnOSKDVQs6c!7lkuWJxs3>;}|=@I?a_9(^j#oMfo=T|^*vNXzV1xO8ZF!%xHyPw3mZ+$loJehVM;S0 zAjSsH_bQ+Zc7P&OBqtxDRrFX0P+`wdZ~UJOCp&TPKA&N;eY%d zC*S#9x|}CQe7yfms3ZfRHRx0%0`dB~YPDx5VvwLsQBTE2Sbw8=_}qFuEwKxa#k{&6 zuNAl9Kzw1vKf)lKnDuz3BxELeziNF9VU%Xs58n}9UuFnPTcL=TGD3$?Tu@ zPtQ>qHM-S(5H3u;q^VvSvJrLzjUi8DO91{! zcXs(!TA2wJuQd~fqp9L_xYAP4uu&E~s4h7Ce0o4_|B%gLf*V#y7bIb7AYrvTdTY?_ z!TI8X&)VW`q>}%puQeyK%uo!T>e`Dk@&a8f7cj(jVESC{O${|W<{SgNhnOUPLN)7mv$M$(!8HB9C6I4Sv9c zQku=5@j|75g>dNkDKJq(=KG(WPtgLzAGg>j-%n0PiiUz#@jUkSNsRzm#{B^5Ys>Rx zBDC-lU9K2{!(Mq&#-p*$o`DU=mSP=}Cmls9wEF1beAfcRSS=E&(}WE8;tX;8l#hlA zIhWgebZlz7Sk0tY_7vR3#TgmFqLpvQu0vi)YRaLX?d8Z%H5cDs$mRyVL#1 z>%kwreu>N3qP^6bm19yUB=`BZNIIRHcj>jM2WMp{(E>uik`kgkJYlgmm>?aJ&K%^l z+~hZk_v@-~c>GieRb=wG&{Osl(=i%qTC|kDNZ&gOIyv-JPnoJcFl+I`za97K@i)W8 zCr3wV6I|io(9zP}K%c&hm9}MUd>xqf#>R(5MYp3oF{qf1J>b3zH9h>}`_5GHIlU?s zqF8MgtsXyVCpC^w3+nDXaw@O5YOFNzuBVhKiDol7^0y zQpI8H_DeOwCcuZ*O$toGvSO^B?;}W&8qrAG9ysfrFcGKN;GZ2(7yYr<{+8=LB21^*Et2&4Q7Rn-2@U4tWLJ2Jn)wBmYh0mX z*a#CRTF?|KYO7FHQlKB7o|Hqd$qIiL^i3G7ms1Zrl@xY^yiidddV+(pKSW!sR%&Y0 z_t19Tu(a(4j(A<@$M@$M;h>t9nWsi^@{|d{ix<=<2sAmn)DLt%lCkp4(I$`SaOakl zVao^%=ZnOKhKh3W%I%$rl&$ieG4GH?l0b2#p`+|6>m}4N?SazCF*r@g`fKYDhUUEK z;I@y9l(=yB_J=7hk)WD-*2_|&fY)8~ZtGePS5OTT*?{5;oj!nGZ9K7JTEj&xDLaiY zd6Tp2i+6Po8bJl0_M017U8K}&R|u7iAWQJ{_HPe`8eoveQKzaY z=@F=6cmR=;;ffWMGw|!%&u>C!+faRNly||h8i9o9xFb2$!OA1sZ$iJjW@gR zHB^F$D?w_cJL&u5GuX3%yVf(N3o2`>XjL-j!=Q}? z+MDCq7<%~=R=XLz6L7c9gm6EEWC>;ILM~}BMelnNsbGFsPubaI8w%DO>&#M`q*QZrp(CG8h zywKE^_Z?x~#5ITS`aBO`@c+CB6!Zva~|Vu{=7=AE9beM)mPGezDockp8Y=97cd=N>U7H7h44|Mfeg zH}GJU1;-2idb`baa*}~gDd73ykM$>a+h*5Tptk(sw^{|qD53*5oy}Mv=qNE50bu#EgU8qIKK#DtbGJ)X7sIhd z)oPN#wu~(=jd(d?EBpK%`zhEE?KY$)I%%@)>7*%5h2D!YBZ?}+E_OicIS7AiSDZr06k3qK&z>C?fE4O~SYgMBL22 zlGUn`F!13WzYSkIPF>lWW*JN}tC*{D8SY)n~fQ-S$(H# zps@@a+(LQ1srZXqYl>3ChDh^i<337&0LTM&PN@!2QKPMG`Ex>oT0|gT=BU9YgI|0v zu((mnEf<2I6I^XxsG2TF3l)HJuLxOqj%>S57glBTh1a==DH2hrrM5q!hGz$ae6a(k znH^;GOUuIrPR8blLPf%OvWB;SENnd(4qzev7x(9&pf{jDBp$dgW_g`pO=SZ0S*u(B zt(G`WVS-wDGZ;3vw^nT7$r6`piAur0nVKpUp$AiSNg=>VSR)f-sM%1h9*$WeSz5#j zSCXb2uXeFAWl5A2Qi`7QHqrzNR7Go#A~20^Fmx8owkJ=l|NgA7*LMxH0n1L1ltBq&Gg{Ru-*OGE8;lb_G0LbeHn+uDh~RgQ%{5WD4`Z`Au{QT7qqF~V zp~XgYm#??0*=9WkOc?E)^V4u1GZbrokc-jg^i9ua3+Mi3jQu{mH8%M zQ`zkG-l?JaoHd(EZ#~B1uO5Xo_ffwEPuI{Gx=sQJ;ix8(v4TMsYCD;!(R|57&mH?RQYt^sk%SZ*R}3++TxvO13$i zwXWxW?|7y_JL}z#I}*qcu5OnuqJRpCofTw5WYEL24v?nCqQDYin!- ztPX>LYCm5u`t;U`h(apMfyVct91tC{BvgbAlkXkmRISKpJ=*Nm-NZ34pS>`AuFo+e zSelV0kflfPwzb+%R%wdLxc40UrH|OD&R2X64})FL-MJNk#MJ!c9F2F|^rZd)!G37C zZHG4;kuC3p;bRMFFT=^h0$^|$yk+yJ zLDgdbAJzFfU6$WVO6tDs^%24Two}epey0f~?a*?ApBVZ#p1|Ou;3DJkMcTfV<$Nyt z>({DuTwyUd`vs!Kodw5_r#hl-9MIX>vO4m@^82ijCi0o|&0bk%gn22-0b!k{UZkt!USY0NI^<=Z=V_eOlkM2M%7e#3W-6q4MW^s9B~b{R=Pig*L(tG)e`;F_?U&#|;PAFjj`oRusj8y=2(gIa=Kv;NYMFfFWu=;TEh_ zk;7fXjMrxh^!s+utdjHGwgRbrpS$A_Zugh$uF#FW+-;?yu3xm&w(}kVbKdakupmXFJ;L{X&@+AJmwC>mCVIo*qj(3>H}A(D&Y2Q-Gxc$?_&w3je`w!w3| zJRG+tZ+o>HzzW@KHMu-Kf~sEecsjkE)gBFyMjlN|K@N@!2dmU);cl*iLY`4qv1pds z0j~x8;_Xv)`y6du%Hbo?($mWVp3qNZ0UEDTtmnpf<9J)`Ck|S&48x=0L&M9)f)Z50 z4Uz8 zxY6l0>!;of-&K#<4C1*7XFw+RZL^s?z2Bt1XkSq;^u zi`J3D-QaN7D-^)sZHUe4OKZdMCN4;s1A}efdzm%d0YpPHDADJxUmOcP_3vq2=7Y0d6|fXBBqbmJ z0B;*;?EBs8)eLB{vm=l+W3XzMs8!=cZBOH>;nt|u7ZicPsu|jeZ6%p2*m-GP{D?9a zByChLA&h@7xxmYu6pLcDe0A~F?6tq9Qa28U!(oiz-}aZ7r!XnbxfvqtcCH~XXfXTK z^J2}44F!+XyZm9sf!}b0Jc4Li!sD;`(`P(uf)nI&#V?tTXgdeQ8Dz|^M@c2s*$fl* zloK8|=i>@V?A!+5kwg&E9o{w@u1|O^ej!t7FJ@$%L)s-?#kT5}}j;F7P=WOQs$HH?x_FV>j;}Zsj1j9MoqNa|y zCaUQok%mBD5t`IAK)2Z+a9;#jc_!L^erL@03!iC{oIR06(#Wa7x(O{uR2ibpGpKjfAgPbkXCnCyQHrM>}Mixb(zOKYYN_>wPU0}RDJ-2>jN6M*OA z4MecmN^p>ZI)5R!bRJcmmeu{u%%C1d92diZYX0K^)DMjFVk0^<1o& z0XLILY+fk&JmFlG#BvAAr2?Atvl5#0*m^UAincF_0&Epjz?ZD;i*>$PMIJioWU~qq z8AW^;**WQ=Qga*<>VAU-nN1-K_R{-9P(XI?4XzNk|DIvId&85UuK~n|kGs`5Pfmid zJlPhZWsQ#cw?P>rDFo(b_i*-*WDl*@Bi9N*^%U!F0M8cj zXf~HsKbyO~QoPRY8$1^G;#gOeD5dG(YUQ7}*H17V;cvoV;6tM-NJBfNV%aiRJCjMf zVA&!Noo&akFe#b8xiHk8<84O5#T!#+hWh|oY-r8|Hjll7zoCU`q zoB){HZPV3EQpDsfUk(@Ry%mSKHa_?|oEJTvIS~f?vfk%DgrM46T0C}8s+x?T&l4O! z+NTR3zMh~+COLxO8{GZIZSNsImN*OUYP~j5zp6q1>7?PZ^Ynu9eILL5=(0@xMhEq~ z8l~I`2CQZvWNtyAfnz-m2 zZWhDs?)fN)kR{9bc

g9*{msxop4y&j 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 Z{{t(u{V{<1^rZj*002ovPDHLkV1lWfLc9O~ literal 0 HcmV?d00001 diff --git a/docs/content/img/language-recoverct-700.png b/docs/content/img/language-recoverct-700.png new file mode 100644 index 0000000000000000000000000000000000000000..030da9f8f85e3bafd40618ff8aa93afa51435ef6 GIT binary patch literal 27794 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 brackets. In this particular case `write()` constraint is optional and is only added to the body of the production in case the condition is satisfied (a location is written to, only if the local variable has an initialiser). +The aim of rules defined by handlers is again twofold: firstly, they may serve as regular «checking» rules, and also, most importantly, they contribute constraint productions. These are created with a DSL that allows mixing of productions and Java code, and can also include constraint fragments inside a production template. + +The following example is from the experimental *control flow* aspect for baseLanguage. It demonstrates how a production is constructed using a template. A production template is enclosed into a pair of `%% … %%` symbols and yields constraints wrapped into special `<% … %>` brackets. In this particular case `write/2` constraint is optional and is only added to the body of the production in case the condition is satisfied (a location is written to only if the local variable has an initialiser). ![](img/language-writelocal-750.png) -_(example of code rule template)_ +_(example of rule with production template)_ A handler is a concept in language `jetbrains.mps.lang.coderules`. ![](img/language-handlerhead-300.png) _(example of a handler declaration — without contents)_ -Keyword `extends` allows to specify another handler, which is extended by this one. All constraint productions generated by rules in this handler will have higher priority. This enables to override the original handler’s behaviour. +Keyword `extends` allows to specify another handler, which is to be extended. All constraint productions generated by rules in this handler will have higher priority. This enables to override the original handler’s behaviour. -Only declared constraints are allowed to be used in the heads of productions in rule templates. Handler should declare one or more constraints, unless it only uses the constraints from handlers being extended. Constraint declaration consists of name and arity, which together constitute a *constraint symbol*. Constraint’s arity is fixed. +Only declared constraints are allowed to be used in the heads of productions in rules of this handler or its extensions. Handler should declare one or more constraints, unless it only uses the constraints from handlers which it extends. Constraint declaration consists of name and *arity*, which together constitute a *constraint symbol*. Constraint’s arity is fixed. -Rule templates can specify applicable concept, either exactly or including its subconcepts. One can also declare *standalone* templates, which are triggered automatically on every invocation of constraints program. +Rules can specify applicable concept, either exactly or including its subconcepts. One can also declare *standalone* rules, which are triggered automatically on every rules application. ![](img/language-vardecl-600.png) -_(rule template matching concept instances with condition block)_ +_(example of rule matching concept instances with condition block)_ -A condition, is specified, is checked before applying the rule. +An applicability condition, if specified, is checked before applying the rule. ![](img/language-hasbound-550.png) -_(standalone rule template without input)_ +_(example of standalone rule without input)_ -The contents of a rule template is a block of code that gets executed when the template is applied to the source model. If the input is specified, the declared parameter is available in the body. When no input is specified, the rule becomes «standalone» and is automatically executed once per every application of templates. +Contents of a rule is a block of code that gets executed when the rule is applied to the source model. If the input is specified, the declared parameter is available in the body. When no input is specified, the rule becomes «standalone» and is automatically executed once per every rules application. -***What other features are available aside from constraint productions?*** +Rules may affect the scope of model locations that are processed during the application session. Suppose a production responsible for typechecking a location relies on presence of productions that are only available if some other location is processed as well. To guarantee that a certain model location is processed during the application session one uses `require` statement. -Constraint productions can be created at any place within the body of a rule template. A production has three main parts called head, guard, and body. The head defines what constraint trigger this production, and it can only contain constraints defined by the handler or one of the handlers it extends. The body can contain any visible constraints, as well as *predicates*. A production must include either the body or the head, no production can omit both. The guard is optional, and it can only contain predicates. +![](img/language-recoverct-700.png) +_(example of using `require` statement)_ + +#### Constraint Productions + +*Constraint productions* can be created at any place within rule body. A production has three main parts called head, guard, and body. The head defines what constraint trigger this production, and it can only contain constraints defined by the handler or one of the handlers it extends. The body can contain any visible constraints, as well as *predicates*. A production must include either the body or the head, no production can omit both. The guard is optional, and it can only contain predicates. Both the head and the body can declare *logical variables*. By default a logical variable ranges over *terms*, although any POJO may be serve as a value. ![](img/language-compatibleWith-300.png) _(constraint production declaring logical variables)_ -A production with an empty head, that is not declaring any constraints to serve as the input, is considered an *automatic* production and is triggered automatically on start of constraints program execution. +A production with an empty head, not declaring any constraints to serve as the input, is considered an *automatic* production and is triggered automatically on start of constraints program evaluation. In production’s head constraints can be declared as either *kept* or *replaced*. Briefly put, the constraints that are *kept* are left alone after a production is fired, whereas the *replaced* ones are discarded after the head has been matched. Replaced constraints are marked with tilde `~`. -A production is triggered when there are constraint occurrences matching all constraints in production’s head. When a constraint with logical variable as one of its arguments is matched, that variable becomes bound to the corresponding argument of the matching occurrence. The scope of this binding is the guard and the body of the production. +A production is triggered when there are constraint occurrences matching all constraints in production’s head. When a constraint with logical variable as one of its arguments is matched, that variable becomes bound to the corresponding argument of the matching occurrence. The scope of the binding is this production’s guard and body. Pattern matching is also possible with terms, optionally containing logical variables, serving as patterns. For this to work, a logical variable that serves as a constraint argument should have a pattern attached. @@ -76,18 +86,18 @@ _(production with pattern matching)_ Everywhere where locations in the source code (model) must be referenced, node references are used, which are introduced with the `@` symbol. ![](img/language-typeof-550.png) -_(example of a constraint argument referring to a location)_ +_(example of constraint argument referring to a location)_ -Whereas the production’s head can only contain constraints, there are also other logical clauses that are used in the guard and the body. +Whereas the production’s head can only contain constraints, there are also other logical clauses that are used in guard and body. -A *predicate* is a built-in construct that serves two purposes: when used in the guard, it serves to query if a condition is satisfied, and when used in the body it asserts this condition. An example is `unifies` predicate displayed as `=`, which tests if its arguments can be unified. There are also predicates that can only be queries, such as `isFree()` or `isBound()` testing if a logical variable is free or has value assigned. +A *predicate* is a built-in construct that serves two purposes: when used in guard, it serves to query if the condition is satisfied, and when invoked from body, it asserts the condition. An example is `unifies` predicate, displayed as `=`, which tests if its arguments can be unified if used in guard, and invokes the actual unification if called from body. There are also predicates that can only be queries, such as `isFree/1` or `isBound/1`, testing if a logical variable is free or has value assigned. Production’s guard can only contain predicates, and the body can contain both constraints and predicates. ![](img/language-unify-300.png) _(`unifies` predicate used in the guard and in the body)_ -Arbitrary Java code can be called with `eval()` predicate. It accepts either an expression of `boolean` type, in which case it can be used in the guard, or expression of any type, such as static method call, which can be inserted in the body. +Arbitrary Java code can be called with `eval/1` predicate. It accepts either an expression of `boolean` type, in which case it can be used in guard, or expression of any type, such as static method call, which is available in body. ![](img/language-recover-500.png) _(example of using `eval()` predicate)_ @@ -100,7 +110,7 @@ _(example of using `eval()` predicate)_ #### Query -Query is the entry point to a constraint program. The only purpose of a query is to activate constraints that trigger computation defined by productions created by handlers. +Query is the entry point to a constraint program. The only purpose of a query is to activate constraints that trigger computation implemented by constraint productions. ![](img/language-query-350.png) _(example of a query)_ @@ -109,7 +119,7 @@ A query is discovered by the API through its *kind*. Query kind specifies parame #### Macro table -Macros allow to have parameterised constructors for terms. They can either create terms using nodes coming from the source model, or use the parameters to fill in values. By contrast with rule templates, macros are always explicitly invoked. +Macros allow to have parameterised constructors for terms. They can either create terms using nodes coming from the source model, or use the parameters to fill in values. By contrast with rules, macros are always explicitly invoked. This feature may come in handy when data types used by the constraint program are complicated and include many levels of containment. For example, type checking with *code rules* relies on types being terms, which means types can contain other types. @@ -122,15 +132,15 @@ Macro *expands* instances of specified concept. This means the macro can be invo ***Expand/call from production body*** -Macro body is a code template, with every constraint or predicate produced from this template being inserted into the production body at the invocation site. There is a special logical variable available within macro body, `macroLogical`, which captures the logical variable on the left side of `expand` or `call` predicate. +- Macro body is a code template, with every constraint or predicate produced from this template being inserted into the production body at the invocation site. There is a special logical variable available within macro body, `macroLogical`, which captures the logical variable on the left side of `expand` or `call` predicate. ***Substitutions*** #### DataForm table -DataForm table contains *data form* declarations, a.k.a. *terms*. A term is a simple recursive data type that is suitable for implementing unification. Also, terms can model any other data structure, in particular they are suitable for representing types in a programming language. +DataForm table contains *dataform* declarations, a.k.a. *terms*. A term is a simple recursive data type that is suitable for implementing unification. Also, terms can model any other data structure, in particular they are suitable for representing types in a programming language. -Data form is defined by its symbol and its features, which can be a POJO, a child data form, or a list of data forms. A feature may have a default value provider. A data form extending another data form adds new features or provides default values for existing ones. +Dataform is defined by its symbol and its features, which can be a POJO, a child dataform, or a list of dataforms. A feature may have a default value provider. A dataform extending another dataform adds new features or provides default values for existing ones. ![](img/language-classifiertype-300.png) _(example of a dataform definition for classifier type)_ diff --git a/docs/content/overview.md b/docs/content/overview.md index 8c4f242e..1802defc 100644 --- a/docs/content/overview.md +++ b/docs/content/overview.md @@ -6,47 +6,47 @@ weight: 20 # Overview -Analysis of source code (model) with *code rules* can be described as a two-phase process. +Analysis of source code or model with *code rules* can be described as a two-phase process. -In the first phase, the languages used by the model being analysed and their prototypes (meaning the languages that are being *extended*, but not used directly) are surveyed for the appropriate code rules aspect model, which is «types» in case of type checking, for example. The contents of code rules aspect model is a contribution of this particular language. All templates are applied to the source code, with templates coming from extension languages having higher priority. +In the first phase, the languages used by the model being analysed, and their prototypes (meaning the languages that are being *extended*, but not used directly) are surveyed for the appropriate *code rules* aspect model, which is `types` in case of type checking, for example. Contents of this aspect model is a contribution of this particular language. All rules within this model are applied to the source model, with rules coming from extension languages having higher priority. -The outcome of this phase is a constraints program, which is a collection of handlers, which in turn represent lists of productions. This «program», however, exists in memory only, it does not have textual representation. Aside from generating productions, the rules can also process the model normally, reporting errors as usual. +The outcome of this phase is a *constraints program*, which is a collection of *handlers*, which in turn represent lists of *productions*. This «program», however, exists in memory only, it does not have any textual representation. Aside from generating productions, the rules can also process the model normally, reporting errors as usual. -This phase runs in «read action», therefore blocking potential writes, which means the editor may become unresponsive if a write action is requested. Ideally the rules should finish quickly and postpone all heavy load to the next phase, which can be run in the background, as the access to `SModel` is no longer necessary. +The first phase runs in «read action», therefore blocking potential writes, which means the editor may become unresponsive if a write action is requested. Ideally the rules should finish quickly and postpone all heavy load to the next phase, which can be run in the background, as the access to `SModel` is no longer necessary. -The second phase is evaluation of the constraints program that was created in phase one. The evaluation starts with a query, which serves as an entry point to the program. For example, type system defines `TYPECHECK` and `CONVERT` queries, aimed at running type checking and testing if a type can be converted to another type, correspondingly. Queries are declared in the same aspect model. +In the second phase the constraints program that was created in phase one is evaluated. Evaluation starts with a query, which serves as an entry point to the program. For example, type system defines `TYPECHECK` and `CONVERT` queries, aimed at running type checking and testing if a type can be converted to another type, correspondingly. Queries are declared in the same aspect model. ![](img/overview-convertsto-500.png) _(example of a query)_ -In the above example the query defines two logical variables (A and B) of type `term`, which serve to represent types internally. First, both query parameters `to` and `from` are *expanded*, meaning that their `SNode` representations are converted to terms, and then the constraint `convertsTo(A, B)` is activated, kicking off the process of evaluating the program. In case productions triggered by `convertsTo()` constraint all evaluate to true, the query is deemed successful, and if there is at least one production that evaluates to false, the query fails accordingly. +In the above example, the query defines two logical variables (A and B) of type `term`, which serve to represent types internally. First, both query parameters `to` and `from` are *expanded*, meaning that their `SNode` representations are converted to terms, and then the constraint `convertsTo(A, B)` is activated, kicking off the process of evaluating the program. In case productions triggered by `convertsTo/2` constraint all evaluate to true, the query is deemed successful, and if there is at least one production that evaluates to false, the query fails accordingly. -One nice feature of using code rules is the ability to abstract away from type structure defined by the language. For example, one may decide to represent all primitive types as a term `primitive(kind=)`. Terms can also incorporate values, so creating an inference rule which checks if a particular constant fits the given type, be it an `int` or a `char`, is trivial. +One nice feature of using code rules is the ability to abstract away from type structure defined by the language. For example, one may decide to represent all primitive types as a term `primitive(kind=)`. Terms can also incorporate values as regular Java objects, so creating an inference rule which checks if a particular constant fits the given type, be it an `int` or a `char`, is trivial. -Having an internal representation for types also means, that if type system is required to represent types as instances of `SNode` to the user, this has to be addressed by the query design. For instance, a type checking query may consist of two constraints: +Having an internal representation for types also means, that if type system is required to represent types as instances of `SNode` to the user, this has to be addressed by the query design. For instance, a type checking query may consist of two constraint activations: ![](img/overview-check-300.png) -_(example of a production)_ +_(example of a query production)_ -Here, the first constraint `checkAll()` fires type checking, whereas the second `recoverAll()` is responsible for restoring terms to `SNode` instances and reporting them back to the user. Joining the two constraints with a conjunction establishes the order in which these are evaluated. +Here, the first constraint `checkAll/0` fires type checking, whereas the second `recoverAll/0` is responsible for restoring terms to `SNode` instances and reporting them back to the user. Joining the two constraints with a conjunction establishes the order in which these are evaluated. An of course, if something can go wrong, it will. In case type inference is unsuccessful, the second stage has no chance of being evaluated. To account for that, a partial backtracking was added to the language of production templates, which helps recover from certain failures. ![](img/overview-check2-300.png) -_(example of a production with alternative body branch)_ +_(example of a query production with alternative body)_ -Here, `recoverAll()` constraint is moved out to an «*alternative branch*» of production body, which allows it to be activated even if there was an error while processing the main branch. +Here, `recoverAll/0` constraint is moved out to an «*alternative branch*» of production body, which allows it to be activated even if there was an error while processing the main branch. -To illustrate how automatic binding of logical variables work, consider the following example. The constraint `typeOf()` associates a type with a location in source code, and `convertsTo()` ensures its 1st argument can be converted to the 2nd, which must both be types. +To illustrate how automatic binding of logical variables work, consider the following example. Constraint `typeOf/2` associates a type with a location in source model, and `convertsTo/2` ensures its 1st argument can be converted to the 2nd, which must both be types. ![](img/overview-assignment-700.png) -_(example of rule template)_ +_(example of rule with production)_ -The production is triggered when both locations referred to by `ae.lValue` and `ae.rValue` have their types assigned, as both `typeOf()` constraints must be present for a match to be successful. Once production’s head is matched, both logical variables `LType` and `RType` become bound to whatever was the 2nd argument of first and second `typeOf()` constraint, respectively. +This production is triggered when both locations referred to by `ae.lValue` and `ae.rValue` have their types assigned, as both `typeOf/2` constraints must be present for a match to be successful. Once production’s head is matched, both logical variables `LType` and `RType` become bound to whatever was the 2nd argument of either occurrences of `typeOf/2` constraint. It’s important to note, that although on successful match both `lValue` and `rValue` have types, it’s not guaranteed that these types are *ground*. A type may be represented by a free logical variable, or a term containing free variables. Another very important thing to notice is that a logical variable enjoys full privileges of being an argument to a constraint. Which means, if in the above example both variables are free, and `LType = RType`, then both locations will have essentially the *same* type (in the sense of «same instance»), not just matching types. -The following example illustrates the use of *pattern matching* in production’s head. Here the first argument to constraint `convertsTo()` in the head is a logical variable with pattern expression. In this case the production will only be triggered if the active constraint’s first argument is not a free variable, and it matches the pattern. +The following example illustrates the use of *pattern matching* in production’s head. Here the first argument to constraint `convertsTo/2` in the head is a logical variable with pattern expression. In this case the production will only be triggered if the active constraint’s first argument is *bound* (is not a free logical variable), and it matches the pattern. ![](img/overview-converts-500.png) -_(example of rule template)_ +_(example of rule with production)_ diff --git a/docs/content/todo/todo-evaluating.md b/docs/content/todo/todo-evaluating.md index d4630558..c56846d5 100644 --- a/docs/content/todo/todo-evaluating.md +++ b/docs/content/todo/todo-evaluating.md @@ -1,7 +1,5 @@ # TODO Evaluating Code Rules - - [ ] **aspects** - - [ ] **UI** - [x] Two stages process - [x] apply all rule templates - [x] sort handlers by language @@ -10,6 +8,8 @@ - [x] build program - [ ] evaluate program - [ ] **report problems during evaluation** - - [x] handle errors + - [ ] **handle errors** + - [ ] **UI** + - [ ] **facade API** - [ ] **activation trace view** diff --git a/docs/content/todo/todo-example-typechecking.md b/docs/content/todo/todo-example-typechecking.md new file mode 100644 index 00000000..1a361e44 --- /dev/null +++ b/docs/content/todo/todo-example-typechecking.md @@ -0,0 +1,46 @@ +- [ ] types + - [ ] term table for types + - [ ] classifier type + - [ ] type var type + - [ ] capture type + - [ ] array/vararity type + - [ ] upper/lower bound type + - [ ] wildcard type + - [ ] primitive type: int, bool, etc. + - [ ] void and null + - [ ] macro table + - [ ] classifier type + - [ ] type var type + - [ ] bounds + - [ ] parameterised types + - [ ] types with value +- [ ] Query + - [ ] Typecheck + - [ ] checkall, recoverall + - [ ] ConvertsTo + - [ ] convertsTo() +- [ ] Typechecking + - [ ] Constant values + - [ ] string + - [ ] integer, long, char, … + - [ ] expression + - [ ] dotexpression, dot operation + - [ ] method call + - [ ] **type parameter substitutions** + - [ ] equals/assignment/+assignment + - [ ] + - [ ] ??? + - [ ] method declaration + - [ ] type relations + - [ ] boxing + - [ ] capture + - [ ] coerce + - [ ] conversion + - [ ] primitive subtyping + - [ ] subclassing/promote + - [ ] type parameter + - [ ] containment, hasbound + - [ ] type annotations + - [ ] classifier type + - [ ] type parameters: type var, bound type, wildcard + - diff --git a/docs/content/todo/todo-language.md b/docs/content/todo/todo-language.md index 198968c6..1d1fb584 100644 --- a/docs/content/todo/todo-language.md +++ b/docs/content/todo/todo-language.md @@ -1,11 +1,9 @@ # TODO Language -## Intro -- [ ] templates are usual for MPS -- [ ] applicable to concept/+subconcepts -- [ ] standalone -- [ ] can serve as «checking rule» -- [ ] produce productions to be evaluated +## Language aspect +- [ ] **aspects** + - [ ] language defines aspect (eg. typechecking) + - [ ] languages using this aspect define handlers ## Handler - [x] create handler, optionally extend another handler @@ -15,7 +13,7 @@ - [x] applicability condition - [ ] what purpose does the body serve - [ ] **reporting errors** - - [ ] **_require_ statement** + - [x] _require_ statement - [ ] **what features are available in a rule** - [ ] introduce constraint production - [x] declare logical variables