UInt*
native types are renamed to Nat*
. Should we add Nat
as well (as like an Int
)?~
will change to ^
. (Inspired from Go)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
true
and false
are case
-ed types within Bool
, which are later defined as tokens so that it cannot be used for other purposes.if
, then
, elseif
and else
are syntactic sugars for type matching of Bool
. For example, if cond then truestmt else falsestmt end
is equivalent to given Bool from(cond) case true do truestmt case false do falsestmt end
.expr type
is equivalent to (fun (v); given v case T for T do return T end; end)(expr)
.expr as T
is equivalent to (fun (v:T) -> v)(expr)
.-- 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:
(op _)(prec)
and (_ op)(prec)
for non-associative unary operators. (e.g. -a
is allowed but --a
is not)(op __)(prec)
and (__ op)(prec)
for associative unary operators. (e.g. both -a
and --a
are allowed)(__ op _)(prec)
for left-associative binary operators, (e.g. most arithmetic operators)(_ op __)(prec)
for right-associative binary operators, (e.g. **
)(_ op _)(prec)
for non-associative binary operators. (e.g. <=>
)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 ()->_
.
use token 'then'
use token 'else'
use syntax (cond(>self) then expr1(>=self,lazy) else expr2(>=self,lazy)) := fun
if cond then
\return expr1()
else
\return expr2()
end
end
Technically speaking, lazy
tag when applied to the implementation function (i.e. providing the semantics over given syntax) evaluates to the thunk function ()->T
.
Use cases for %
-prefixed reader:
%(nico nico douga (alpha))
%w(hello cruel world)
evaluates to ["hello", "cruel", "world"]
.%"{0:d} {1:s} {2:[s]}" format(4, "foo", ["bar", "quux"])
%/asdf/
%<p class="highlighted">Hello, <em>#{user}</em>!</p>
Use cases for generic quoted literals:
r"asdf"
. But if we have a separate pattern literal do we need this anymore?b"ASDF"
and x"41 42 43 44"
.2"0011 1101 1000"
.use extern
directive
_naru_foo@4
.use pragma
can be used for directly inserting the assembly code during the native code generation.naru ext
package
Struct
is used for classes which memory layout is important.IntNN
classes (or Pointer{...}
) on the fly.Pointer{T}
requires the pointer to be non-null; Option{Pointer{T}}
encodes a nullable pointer.