naru r4 notes

Changes for Near-Future


Currently naru has 37 keywords, of which 26 keywords are fundamental and others are implemented as a syntactic sugar (starred roles):

and     short-circuiting boolean operator (*)
as      type casting (*), renaming
break   block control
but     exception handling, exception handling expression
case    type case specifier
class   concrete class declaration, runtime type attribute
do      generic block
else    conditional (*), conditional expression (*), exception handling
elseif  conditional (*)
end     generic end of block
false   singleton value (*)
finally exception handling finalization
for     loop (*)
fun     function declaration
given   pattern matching
global  outermost scope specifier
if      conditional (*)
in      containment comparison (*)
import  module imports
is      referential equivalence (*)
not     unary boolean operator (*)
or      short-circuiting boolean operator (*)
raise   exception source
retry   block control
return  function returns
self    reference to the enclosing class or instance
super   reference to the base class of the enclosing class or instance
trait   abstract class declaration
true    singleton value (*)
then    conditional (*), conditional expression (*)
type    shortcut class declaration, compile-time type attribute (*)
use     compiler directives
undo    block control
var     variable specifier
while   unrestricted loop
with    explicit finalization, AST augmentation
yield   coroutine returns

Syntax Extension

Simple operator definition

-- token definition.
-- one reason that we split `use token` and `use syntax` is to separate
-- the lexical analysis and parsing.
use token '==', '!='
use token '~~', '!~'

-- operators == and != are defined using `#==#` and `#!=#` multifunctions.
-- precedence can be specified using the following parentheses (as the
-- function call is primitive, parentheses cannot be overridden!).
-- any identifiers can be used for placeholder, but `__` and `_` is special
-- and equivalent to `fresh_name(>=self)` and `fresh_name(>self)` respectively.
use syntax (__ == _)(45)                -- := #==# is implied here
use syntax (lhs(>=self) != rhs(>self))(45) := #!=#    -- self == 45 here.

-- "semantics" can be inlined. if identifiers are used within the syntax
-- then function arguments can be implied (as like uniform definitions).
use syntax (__ ~~ _)(45) := fun (x,y) -> #==#(x, y, epsilon:1e-7)
use syntax (x(>=self) !~ y(>self))(45) := fun -> x != y with epsilon:1e-7

Some common operator definitions:

Chained operators

use token '<'
use token '&&'

-- precedence does not really matter here, as we always enclose terms in
-- parentheses!
use syntax (__ && _)(50)

-- rewriting actually takes place. here `b` is not marked lazy, so it is
-- evaluated earlier than other arguments and `b` in the rewritten form
-- denotes that a single value. this prevents the double evaluation.
use syntax (_ < _)(45)
use syntax (a(>=self,lazy) < b(>self) < c(>self,lazy))(45) -> ((a < b) && (b < c))

Note that in the semantics (:=) form lazy marker means that the argument is given as a thunk function, i.e. of a type ()->_.

Lazy evaluation

use token 'then'
use token 'else'

use syntax (cond(>self) then expr1(>=self,lazy) else expr2(>=self,lazy)) := fun
    if cond then
        \return expr1()
        \return expr2()

Technically speaking, lazy tag when applied to the implementation function (i.e. providing the semantics over given syntax) evaluates to the thunk function ()->T.

Custom literals

Use cases for %-prefixed reader:

Use cases for generic quoted literals:


ikiwiki를 씁니다.
마지막 수정