Adapting Scheme-Like Macros to a C-Like Language Kevin Atkinson, - - PowerPoint PPT Presentation

adapting scheme like macros to a c like language
SMART_READER_LITE
LIVE PREVIEW

Adapting Scheme-Like Macros to a C-Like Language Kevin Atkinson, - - PowerPoint PPT Presentation

Adapting Scheme-Like Macros to a C-Like Language Kevin Atkinson, Matthew Flatt University of Utah 1 ZL Adopts a Scheme-like approach to build C++ from a C like core Why C? The system's programming language Want to make life


slide-1
SLIDE 1

1

Adapting Scheme-Like Macros to a C-Like Language

Kevin Atkinson, Matthew Flatt University of Utah

slide-2
SLIDE 2

2

ZL

  • Adopts a Scheme-like approach to build C++

from a C like core

  • Why C?
  • The system's programming language
  • Want to make life better in that world
slide-3
SLIDE 3

3

Challenges

1.Parsing C Idiosyncratic Syntax While Also Allowing The Syntax to be Extensible 2.Finding Right Hygiene Model 3.Finding Right Reflective Operations

slide-4
SLIDE 4

4

How to Parse This Expression?

f(x/2, y)

Function Call? Macro Invocation?

f(x/2, y) x/2 + y

?

int y = x/2

?

slide-5
SLIDE 5

5

Parsing Overview

  • ZL doesn't parse in a single linear pass
  • Iterative-deepening approach

Raw Text

Parse Raw Text AST Node Partly Expand Compile R e p a r s e Syntax Object Raw Text Syntax Object Raw Text

slide-6
SLIDE 6

6

Parsing Details

"inline int f() {int x = 10; return x;} int main() {return f();}" Parse Expand & Compile (@ (stmt inline int f ('()' "") ('{}' "int x = 10; return x;") (stmt int main ('()' "") ('{}' "return f();")))

Top-Level Environment

(stmt int main ...)

...

(stmt inline int f ...)

...

slide-7
SLIDE 7

7

...

(stmt inline int f ...) (fun f (.) (int) :inline ('{}' "int x = 10; return x;"))

Top-Level Environment

Expand Compile ('{}' "int x = 10; return x;")

Function

...

(stmt int main ...)

...

slide-8
SLIDE 8

8

...

('{}' "int x = 10; return x;")

Function

(block (stmt int x = 10) (return (exp x))) Expand & Reparse Compile

Block

(stmt int x = 10)) (return (exp x))

... ...

slide-9
SLIDE 9

9

Pattern Macros

macro or(x, y) { ({typeof(x) t = x; t ? t : y;}); }

  • r(0.0,t)

({typeof(0.0) t0 = 0.0; t0 ? t0 : t;});

slide-10
SLIDE 10

10

Syntax Macros

"foreach (x in con) printf("%d\n", x);" (foreach x con ('{}' "printf("%d\n", x);"))

smacro foreach (id, container, body) {...}

Parse Expand In Source Code: Add to PEG Grammer: <foreach> "foreach" "(" {ID} "in" {EXP} ")" {STMT}

slide-11
SLIDE 11

11

Procedural Macros

Syntax Forms: syntax make_macro new_mark Callbacks: match replace error

Syntax * or(Syntax * syn, Environ *) { Match * m = match(NULL, syntax (_, x, y), syn); return replace(syntax {({typeof(x) t = x; t ? t : y;});}, m, new_mark()); } make_macro or;

slide-12
SLIDE 12

12 float pi = 3.14159; Syntax * area_circle(Syntax * syn, Environ *) { Mark * mark = new_mark(); Match * m = match(NULL, syntax (_, R), syn); UnmarkedSyntax * r = syntax { ({float r = R; pi*r*r;}); }; return replace (r, m, mark); } make_macro area_circle; int main() { float pi = 3.14; float r = 10; ... area_circle(r) ... }

Procedural Macro Example

slide-13
SLIDE 13

13 float pi = 3.14159; Syntax * area_circle(Syntax * syn, Environ *) { Mark * mark = new_mark(); Match * m = match(NULL, syntax (_, R), syn); UnmarkedSyntax * r = syntax { ({float r = R; pi*r*r;}); }; return replace (r, m, mark); } make_macro area_circle; int main() { ... ... area_circle(r) ... } ('0, )

pi => ...

Expansion of area_circle(r)

slide-14
SLIDE 14

14 float pi = 3.14159; Syntax * area_circle(Syntax * syn, Environ *) { Mark * mark = Match * m = match(NULL, syntax (_, R), syn); [R => r] UnmarkedSyntax * r = syntax { ({float r = R; pi*r*r;}); }; return replace (r, m, mark); } make_macro area_circle; int main() { ... ... area_circle(r) ... } ('0, )

pi => ...

Expansion of area_circle(r)

slide-15
SLIDE 15

15 float pi = 3.14159; Syntax * area_circle(Syntax * syn, Environ *) { Mark * mark = Match * m = [R => r] UnmarkedSyntax * r = syntax { ({float r = R; pi*r*r;}); }; return replace (r, m, mark); } make_macro area_circle; int main() { ... area_circle(r) ... } ('0, )

pi => ...

Expansion of area_circle(r)

slide-16
SLIDE 16

16 float pi = 3.14159; Syntax * area_circle(Syntax * syn, Environ *) { Mark * mark = Match * m = [R => r] UnmarkedSyntax * r = syntax { ({float r = R; pi*r*r;}); }; return replace (r, m, mark); (syntax { ({float r = R; pi*r*r;}); }, [R => r], ); } make_macro area_circle; int main() { ... area_circle(r) ... } ('0, )

pi => ...

Expansion of area_circle(r)

('0, )

pi => ...

slide-17
SLIDE 17

17 float pi = 3.14159; Syntax * area_circle(Syntax * syn, Environ *) { ... return replace (syntax { ({float r = R; pi*r*r;}); }, [R => r], ); } make_macro area_circle; int main() { ... ... area_circle(r) ... ... ({ float r'0 = r; pi'0 * r'0 * r'0; }) ... }

Expansion of area_circle(r)

('0, )

pi => ...

slide-18
SLIDE 18

18 float pi = 3.14159; Syntax * area_circle(Syntax * syn, Environ *) { Mark * mark = new_mark(); Match * m = match(NULL, syntax (_, R), syn); UnmarkedSyntax * r = syntax { ({float r = R; pi*r*r;}); }; return replace (r, m, mark); } make_macro area_circle; int main() { float pi = 3.14; float r = 10; ... area_circle(r) ... }

Hygiene System

({float r = r; pi * r * r;})

slide-19
SLIDE 19

19 float pi $pi0 = 3.14159; pi => $pi0

slide-20
SLIDE 20

20 float pi $pi0 = 3.14159; Syntax * area_circle(Syntax * syn, Environ *) { Mark * mark = new_mark(); ... } make_macro area_circle; pi => $pi0

slide-21
SLIDE 21

21 float pi $pi0 = 3.14159; Syntax * area_circle(Syntax * syn, Environ *) {...} int main() { float pi $pi1 = 3.14; float r $r0 = 10; ... area_circle(r) ... } r => $r0, pi => $pi1, area_circle => ... pi => $pi0

slide-22
SLIDE 22

22 float pi $pi0 = 3.14159; Syntax * area_circle(Syntax * syn, Environ *) {...} int main() { float pi $pi1 = 3.14; float r $r0 = 10; ... area_circle(r) ... ... ({ float r'0 = r; pi'0 * r'0 * r'0; }) ... } '0 => pi => $pi0 r => $r0, pi => $pi1, area_circle => ... pi => $pi0

slide-23
SLIDE 23

23 float pi $pi0 = 3.14159; Syntax * area_circle(Syntax * syn, Environ *) {...} int main() { float pi $pi1 = 3.14; float r $r0 = 10; ... area_circle(r) ... ... ({ float r'0 $r1 = r; pi'0 * r'0 * r'0; }) ... } Mark Becomes Part of The Name r'0 => $r1, r => $r0, pi => $pi1, area_circle => ... pi => $pi0 pi => $pi0 '0 => pi => $pi0

slide-24
SLIDE 24

24 float pi $pi0 = 3.14159; Syntax * area_circle(Syntax * syn, Environ *) {...} int main() { float pi $pi1 = 3.14; float r $r0 = 10; ... area_circle(r) ... ... ({ float r'0 $r1 = r $r0; pi'0 * r'0 * r'0; }) ... } pi => $pi0 pi => $pi0 r'0 => $r1, r => $r0, pi => $pi1, area_circle => ... '0 => pi => $pi0

slide-25
SLIDE 25

25 float pi $pi0 = 3.14159; Syntax * area_circle(Syntax * syn, Environ *) {...} int main() { float pi $pi1 = 3.14; float r $r0 = 10; ... area_circle(r) ... ... ({ float r'0 $r1 = r $r0; pi'0 * r'0 * r'0; }) ... } '0 => pi => $pi0 pi => $pi0 pi => $pi0 r'0 => $r1, r => $r0, pi => $pi1, area_circle => ... Look Inside the Mark

slide-26
SLIDE 26

26 float pi $pi0 = 3.14159; Syntax * area_circle(Syntax * syn, Environ *) {...} int main() { float pi $pi1 = 3.14; float r $r0 = 10; ... area_circle(r) ... ... ({ float r'0 $r1 = r $r0; pi'0 $pi0 * r'0 * r'0; }) ... } pi => $pi0 pi => $pi0 r'0 => $r1, r => $r0, pi => $pi1, area_circle => ... pi Strip Mark '0 => pi => $pi0

slide-27
SLIDE 27

27 float pi $pi0 = 3.14159; Syntax * area_circle(Syntax * syn, Environ *) {...} int main() { float pi $pi1 = 3.14; float r $r0 = 10; ... area_circle(r) ... ... ({ float r'0 $r1 = r $r0; pi'0 $pi0 * r'0 $r1 * r'0 $r1; })... } pi => $pi0 pi => $pi0 r'0 => $r1, r => $r0, pi => $pi1, area_circle => ... '0 => pi => $pi0

slide-28
SLIDE 28

28 float $pi0 = 3.14159; ... int main() { float $pi1 = 3.14; float $r0 = 10; ... ({ float $r1 = $r0; $pi0 * $r1 * $r1; }) ... } Everything Resolves Correctly

slide-29
SLIDE 29

29

Bending Hygiene:

Replace Context

  • datum->syntax-object =>
  • Contex * get_context(Syntax *)
  • Syntax * replace_context

(UnmarkedSyntax *, Context *)

slide-30
SLIDE 30

30

Bending Hygiene:

Fluid Binding

  • define-syntax-parameter => fluid_binding
  • syntax-parameterize => fluid

fluid_binding this; macro m() {f(this);} int main() {X * fluid this = ...; return m();}

slide-31
SLIDE 31

31

Other API Functions

Syntax * foreach (Syntax * syn, Environ * env) { Syntax * con = ...; if (!symbol_exists(syntax begin, con, mark, env) || ... return error(con, "Container lacks proper method."); ... } make_syntax_macro foreach; int main() { ... foreach(x in container) {printf("%d\n", x);}); ... }

  • Additional API Functions and Examples in Paper
slide-32
SLIDE 32

32

Results

  • Used ZL to Mitigate Problems of:
  • Adding and Removing C++ fields and methods
  • Incomparable ABI's Due to Compiler Changes

(See GPCE'10 Paper)

  • Compile Time Only 2-3 slower than G++
  • No Impact on Run-time Performance
slide-33
SLIDE 33

33

Conclusion

  • Presented Macro System that:
  • Handle C’s rich syntax
  • Preserves Lexical Scope
  • Offers power of Scheme's syntax-case
  • Parts of ZL Also Presented in GPCE'10:

ABI Compatibility Through a Customizable Language

  • Additional Parts Presented in my Dissertation
  • Implementation Available:

http://www.cs.utah.edu/~kevina/zl