5. 5
Powerful Type Inferences
There exist type inferences in recent languages.
Nemerle's type inference is different from:
def fact(n){
| 0 => 1
| _ => n * fact(n - 1)
} // recursive function ( without type annotation )
fact(4) // int -> int is inferred from use-site
6. 6
What's Macro?
Features so-called cacros
➢Lisp's macro
➢Lisp's reader macro
➢Preprocessor macro (in C family language)
➢Hidemaru Macro ← Different meaning
➢Excel Macro(VBA) ← Different meaning
Nemerle's macro is inspired by Lisp's macro
7. 7
What's Nemerle's Macros?
Lexical level macros
➢[Token] -> [Token]
AST level macros
➢ASTNode -> ASTNode
Custom attribute macros
➢Global rewriting of program is allowed using such macros
➢Compile time MOP
8. 8
AST Level Macros
Similar with Lisp's macros
Receive AST of expression and return AST
➢Transformation is written in Nemerle itself
➢Typed AST is handled
Many language constructs is just macros
➢If, while, for, using, printf, lock, etc.
9. 9
Hello, World! In Nemerle
Statically checked printf
using Nemerle.IO;
printf("%d + %d = %dn", 1, 2, 1 + 2) //OK
printf("%d + %d = %dn", 1, 2, "3") //NG
printf("%d + %d = %dn", 1, 2, 3.0) //NG
def format = "%d + %d = %dn"
printf(format, 1, 2, 3) //NG. format must be string literal
10. 10
Using Macros(1)
using System;
macro fact(n: int) {
def loop(m) {//type inference for recursive function
| 0 => 1
| _ => m * f(m - 1)
}
{ def r = f(n); Console.WriteLine("fact({0}" = {1}", n, r); <[ $(r: int) ]> }
}
fact(4) // → 24
11. 11
Using Macros(2)
using System.Text.RegularExpressions;
using Nemerle.Compiler
macro regex(n: String) {
def r = <[ Regex($(n: string)) ]>;
try { _ = Regex(n); r; } catch { | _ is ArgumentException =>
Message.Warning("illegal pattern " + n); r }
}
regex(".*") // OK
regex("**") // → "illegal pattern **" in compile time
12. 12
Using Macros(3)
Swap macros
macro swap(n, m) syntax("swap", n, "and", m) {// new syntax: swap n and m
<[ def tmp = $n; $n = $m; $m = tmp; ]>
}
using System;
mutable x = 10; mutable y = 20;
swap x and y; // diffent syntax
Console.WriteLine("({0}, {1})", x, y); // → "(20, 10)"
13. 13
Solving Maze in Compile Time(1)
using System; using System.Console;
using System.IO.File; using Nemerle.Collections;
using Nemerle.Imperative; using Nemerle.Compiler;
macro SolveMaze(inputFile: String) {
def maze = ReadAllLines(inputFile)
def h = maze.length;
...
}
15. 15
Custome Attribute Macro(Compile Time MOP)
using Nemerle.Compiler; using Nemerle.Collections;
namespace DesignPatterns {
[Nemerle.MacroUsage
(Nemerle.MacroPhase.WithTypedMembers,
Nemerle.MacroTargets.Field)]
macro Proxy (t : TypeBuilder, f : FieldBuilder, iface) { ... }
}
using DesignPatterns;
class Point { public X : int { ... }; public Y() : int { ... }; }
class PointProxy {
[Proxy()] //invocation of Proxy macro
point_ : Point;
}