SlideShare a Scribd company logo
 
Ruby Macros
 
 
“ print 'hello'” :(print 'hello')‏ proc{ print 'hello' }
RedParse.new(“print 'hello'”).parse :(print 'hello')‏ RedParse::CallNode[nil, "print", [RedParse::StringNode["hello",  {:@line=>1, :@close=>"'", :@open=>"'", :@char=>"\""}]], nil, nil,  {:@line=>1, :@not_real_parens=>true, :@offset=>0, :@lvalue=>nil}]
str=:(“hello”)‏ :(print ^str)‏
macro simple(a,b)  :(^a+^b)  end def simple_user p simple(1,2)‏ end
if $Debug macro assert(cond)‏ if RedParse::OpNode===cond and /\A[=!]=\Z/===cond.op left,op,right=*cond :(fail 'expected '+^left.unparse({})+"(==#{^left}) to be "+ ^op+" "+^right.unparse({})+"(==#{^right})" unless ^cond)  else :(fail "expected #{:(^^cond)}, but was not true" unless ^cond)‏ end end else macro assert(cond)‏ end end
def test_assert a=1  b=2 assert a  #ok assert a!=b  #ok assert(a==b) #oops, fails. msg="expected a(==1) to be == b(==2)" assert(nil) #oops, fails. msg="expected nil, but was not true" #ok, that message didn't make a lot of sense... end
Syntax trees are represented by trees of nested Nodes. All  Nodes descend from Array, and their subnodes can be  addressed by numeric index, just like normal Arrays.  However, many subnodes want to have names as well,  thus most (but not all) array slots within the various Node  classes have names. The general rule is that Node slots  may contain a Node, a VarNameToken, a plain Array, a  String, or nil. However, many cases are more specific  than that.
VarNameToken<RubyLexer::Token  #represents variables and constants (ident: String)‏ Node<Array  #abstract ancestor of all nodes (except VarNameToken)‏ +RescueNode  #a rescue clause in a def of begin statement |  (exceptions: Array[Value*], varname: VarNameToken|nil, action: Value)‏ +WhenNode  #a when clause in a case statement |  (when: Value|Array[Value+]  then: Value|nil )‏ +ElsifNode  #an elsif clause in an if statement |  (elsif: Value, then: Value|nil)‏ +ValueNode  #abstract, a node which has a value (an expression)‏ |+ListOpNode  #abstract, ancestor for nodes which are lists of |||  #things separated by some op ||+SequenceNode  #a sequence of statements |||  (Array[Value*])‏ ||+ConstantNode  #a constant expression of the form A::B::C or the like ||  #first expression can be anything ||  (Array[String|Value|nil,String+])‏ |+RawOpNode  #ancestor of all operators (but not . :: ; , ?..:)‏ |||  (left: Value, op: String, right: Value)‏ ||+OpNode  #ancestor of some operators |||+RangeNode  #a range literal node |||+KeywordOpNode #abstract, ancestor of keyword operators ||||+LogicalNode  #and or && || expressions ||||+WhileOpNode  #while as an operator ||||+UntilOpNode  #until as an operator ||||+IfOpNode  #if as an operator ||||+UnlessOpNode #unless as an operator |||+NotEqualNode  #!= expressions
|||+MatchNode  #=~ expressions |||+NotMatchNode  #!~ expressions |+LiteralNode  #literal symbols, integers ||  (val: Numeric|Symbol|StringNode)‏ |+StringNode  #literal strings |||  (Array[(String|Value)+])‏ ||+HereDocNode  #here documents |+StringCatNode  #adjacent strings are catenated (&quot;foo&quot; &quot;bar&quot; == &quot;foobar&quot;)‏ ||  (Array[StringNode+])‏ |+NopNode  #an expression with no tokens at all in it ||  (no attributes)‏ |+VarLikeNode  #nil,false,true,__FILE__,__LINE__,self ||  (name: String)‏ |+UnOpNode  #unary operators ||  (op: String, val: Value)‏ ||+UnaryStarNode  #unary star (splat)‏ |||+DanglingStarNode  #unary star with no argument |||||  (no attributes)‏ ||||+DanglingCommaNode  #comma with no rhs ||  (no attributes)‏ |+ParenedNode  #ugly, parenthesized expressions and begin..end ||  (body: Value)  -OR-  (parentheses)‏ ||  (body: Value|nil, rescues: Array[RescueNode*], ||  else: Value|nil, ensure: Value|nil)  (begin...end and rescue as operator)‏ |+AssignNode  #assignment (including eg +=)‏ ||  (left:AssigneeList|LValue, op:String ,right:Array[Value*]|Value)‏
|+AssigneeList  #abstract, comma-delimited list of assignables |||  (Array[LValue*])‏ ||+NestedAssign  #nested lhs, in parentheses ||+MultiAssign  #regular top-level lhs ||+BlockParams  #block formal parameter list |+CallSiteNode  #abstract, method calls |||  (receiver: Value|nil, name: String,  |||  params: nil|Array[Value+,UnaryStarNode?,UnAmpNode?], |||  block_params: BlockParams, block: Value)‏ ||+CallNode  #normal method calls ||+KWCallNode  #keywords that look (more or less) like methods  ||  #(BEGIN END yield return break continue next)‏ |+ArrayLiteralNode #[..] ||  (Array[Value*])‏ |+IfNode  #if..end and unless..end ||  (if: Value, then: Value|nil, elsifs: Array[ElsifNode+]|Nil, else: Value|nil)‏ |+LoopNode  #while..end and until..end ||  (while: Value, do: Value:nil)‏ |+CaseNode  #case..end ||  (case: Value|nil, whens: Array[WhenNode*], else: Value|nil)‏ |+ForNode  #for..end ||  (for: LValue, in: Value, do: Value|nil)‏ |+HashLiteralNode #{..} ||  (Array[Value*]) (size must be even)‏ |+TernaryNode  # ? .. : ||  (if: Value, then: Value, else: Value)‏
|+MethodNode  #def..end ||  (receiver:Value|nil, name:String, ||  params:Array[VarNameToken*,AssignNode*,UnaryStarNode?,UnAmpNode?]|nil, ||  body: Value|nil, rescues: Array[RescueNode+]|nil, else: Value|nil, ensure: Value|nil)‏ |+AliasNode  #alias foo bar ||  (to: String|VarNameToken|StringNode, from: String|VarNameToken|StringNode)‏ |+UndefNode  #undef foo ||  (Array[String|StringNode+])‏ |+NamespaceNode #abstract ||+ModuleNode  #module..end |||  (name: VarNameToken|ConstantNode, body: Value|nil)‏ ||+ClassNode  #class..end |||  (name: VarNameToken|ConstantNode, parent: Value|nil, body: Value|nil)‏ ||+MetaClassNode  #class<<x..end ||  (val: Value, body: Value|nil)‏ |+BracketsGetNode #a[b] |  (receiver: Value, params: Array[Value+,UnaryStarNode?]|nil)‏ | ErrorNode  #mixed in to nodes with a syntax error +MisparsedNode  #mismatched braces or begin..end or the like
Drawbacks: Pre-processing is very, very slow (because of RedParse)‏ Macro calls must be in some sort of method... straight out macros at the top level won't work Macro blocks and receivers aren't supported Some ruby syntax won't work in files using macros Files using macros must be loaded via Macro.require... not normal require RedParse Node tree format will be changing Macros cannot be scoped

More Related Content

PDF
2 BytesC++ course_2014_c8_ strings
PDF
Combinator parsing
PDF
The Ring programming language version 1.8 book - Part 29 of 202
KEY
Deriving Scalaz
PPTX
Strings CPU GTU
PDF
SPL 13 | Character Array(String) in C
PDF
The Ring programming language version 1.9 book - Part 31 of 210
PPTX
Presentation more c_programmingcharacter_and_string_handling_
2 BytesC++ course_2014_c8_ strings
Combinator parsing
The Ring programming language version 1.8 book - Part 29 of 202
Deriving Scalaz
Strings CPU GTU
SPL 13 | Character Array(String) in C
The Ring programming language version 1.9 book - Part 31 of 210
Presentation more c_programmingcharacter_and_string_handling_

What's hot (19)

PPTX
Practical scalaz
PDF
The Ring programming language version 1.5.3 book - Part 24 of 184
KEY
Scalaz
PPTX
ProgrammingwithGOLang
PDF
The Ring programming language version 1.6 book - Part 26 of 189
PDF
Scala: Functioneel programmeren in een object georiënteerde wereld
ODP
Ruby Basics by Rafiq
PDF
The Ring programming language version 1.5.4 book - Part 24 of 185
PDF
The Ring programming language version 1.3 book - Part 15 of 88
PDF
LeetCode April Coding Challenge
PDF
Leet Code May Coding Challenge - DataStructure and Algorithm Problems
PPTX
Oscon 2010 Specs talk
PDF
The Ring programming language version 1.4 book - Part 6 of 30
PDF
Swift rocks! #1
PDF
The Ring programming language version 1.7 book - Part 27 of 196
PPTX
Arrays matrix 2020 ab
PDF
Fp intro scala
PPTX
TRICK
Practical scalaz
The Ring programming language version 1.5.3 book - Part 24 of 184
Scalaz
ProgrammingwithGOLang
The Ring programming language version 1.6 book - Part 26 of 189
Scala: Functioneel programmeren in een object georiënteerde wereld
Ruby Basics by Rafiq
The Ring programming language version 1.5.4 book - Part 24 of 185
The Ring programming language version 1.3 book - Part 15 of 88
LeetCode April Coding Challenge
Leet Code May Coding Challenge - DataStructure and Algorithm Problems
Oscon 2010 Specs talk
The Ring programming language version 1.4 book - Part 6 of 30
Swift rocks! #1
The Ring programming language version 1.7 book - Part 27 of 196
Arrays matrix 2020 ab
Fp intro scala
TRICK
Ad

Similar to Rubymacros (20)

ODP
Scala 2 + 2 > 4
PPTX
Arrays
PDF
Petitparser at the Deep into Smalltalk School 2011
KEY
Cypher inside out: Como a linguagem de pesquisas em grafo do Neo4j foi constr...
PDF
check the modifed code now you will get all operations done.termin.pdf
PDF
Perl 6 in Context
PDF
Kotlin Basics - Apalon Kotlin Sprint Part 2
PDF
Kotlin, Spek and tests
PDF
verilog HDL introduction - beginners guide
PDF
#include iostream using namespace std; class Array { priva.pdf
PDF
Nik Graf - Get started with Reason and ReasonReact
PDF
Slaying the Dragon: Implementing a Programming Language in Ruby
PPT
Functional techniques in Ruby
PPT
Functional techniques in Ruby
PPTX
Analysis of algorithms
PDF
Programming with GUTs
PPTX
Array, string and pointer
PDF
Quick swift tour
PDF
Get started with Reason
PPT
The JavaScript Programming Language
Scala 2 + 2 > 4
Arrays
Petitparser at the Deep into Smalltalk School 2011
Cypher inside out: Como a linguagem de pesquisas em grafo do Neo4j foi constr...
check the modifed code now you will get all operations done.termin.pdf
Perl 6 in Context
Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin, Spek and tests
verilog HDL introduction - beginners guide
#include iostream using namespace std; class Array { priva.pdf
Nik Graf - Get started with Reason and ReasonReact
Slaying the Dragon: Implementing a Programming Language in Ruby
Functional techniques in Ruby
Functional techniques in Ruby
Analysis of algorithms
Programming with GUTs
Array, string and pointer
Quick swift tour
Get started with Reason
The JavaScript Programming Language
Ad

Recently uploaded (20)

PPTX
SOPHOS-XG Firewall Administrator PPT.pptx
PDF
WOOl fibre morphology and structure.pdf for textiles
PDF
NewMind AI Weekly Chronicles - August'25-Week II
PPTX
Chapter 5: Probability Theory and Statistics
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PPTX
A Presentation on Touch Screen Technology
PDF
Zenith AI: Advanced Artificial Intelligence
PDF
From MVP to Full-Scale Product A Startup’s Software Journey.pdf
PDF
Accuracy of neural networks in brain wave diagnosis of schizophrenia
PDF
1 - Historical Antecedents, Social Consideration.pdf
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PDF
A novel scalable deep ensemble learning framework for big data classification...
PDF
Hybrid model detection and classification of lung cancer
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
Getting Started with Data Integration: FME Form 101
PDF
A comparative analysis of optical character recognition models for extracting...
PPTX
1. Introduction to Computer Programming.pptx
PDF
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
PDF
Encapsulation_ Review paper, used for researhc scholars
SOPHOS-XG Firewall Administrator PPT.pptx
WOOl fibre morphology and structure.pdf for textiles
NewMind AI Weekly Chronicles - August'25-Week II
Chapter 5: Probability Theory and Statistics
Unlocking AI with Model Context Protocol (MCP)
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
A Presentation on Touch Screen Technology
Zenith AI: Advanced Artificial Intelligence
From MVP to Full-Scale Product A Startup’s Software Journey.pdf
Accuracy of neural networks in brain wave diagnosis of schizophrenia
1 - Historical Antecedents, Social Consideration.pdf
gpt5_lecture_notes_comprehensive_20250812015547.pdf
A novel scalable deep ensemble learning framework for big data classification...
Hybrid model detection and classification of lung cancer
MIND Revenue Release Quarter 2 2025 Press Release
Getting Started with Data Integration: FME Form 101
A comparative analysis of optical character recognition models for extracting...
1. Introduction to Computer Programming.pptx
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
Encapsulation_ Review paper, used for researhc scholars

Rubymacros

  • 1.  
  • 3.  
  • 4.  
  • 5. “ print 'hello'” :(print 'hello')‏ proc{ print 'hello' }
  • 6. RedParse.new(“print 'hello'”).parse :(print 'hello')‏ RedParse::CallNode[nil, &quot;print&quot;, [RedParse::StringNode[&quot;hello&quot;, {:@line=>1, :@close=>&quot;'&quot;, :@open=>&quot;'&quot;, :@char=>&quot;\&quot;&quot;}]], nil, nil, {:@line=>1, :@not_real_parens=>true, :@offset=>0, :@lvalue=>nil}]
  • 8. macro simple(a,b) :(^a+^b) end def simple_user p simple(1,2)‏ end
  • 9. if $Debug macro assert(cond)‏ if RedParse::OpNode===cond and /\A[=!]=\Z/===cond.op left,op,right=*cond :(fail 'expected '+^left.unparse({})+&quot;(==#{^left}) to be &quot;+ ^op+&quot; &quot;+^right.unparse({})+&quot;(==#{^right})&quot; unless ^cond) else :(fail &quot;expected #{:(^^cond)}, but was not true&quot; unless ^cond)‏ end end else macro assert(cond)‏ end end
  • 10. def test_assert a=1 b=2 assert a #ok assert a!=b #ok assert(a==b) #oops, fails. msg=&quot;expected a(==1) to be == b(==2)&quot; assert(nil) #oops, fails. msg=&quot;expected nil, but was not true&quot; #ok, that message didn't make a lot of sense... end
  • 11. Syntax trees are represented by trees of nested Nodes. All Nodes descend from Array, and their subnodes can be addressed by numeric index, just like normal Arrays. However, many subnodes want to have names as well, thus most (but not all) array slots within the various Node classes have names. The general rule is that Node slots may contain a Node, a VarNameToken, a plain Array, a String, or nil. However, many cases are more specific than that.
  • 12. VarNameToken<RubyLexer::Token #represents variables and constants (ident: String)‏ Node<Array #abstract ancestor of all nodes (except VarNameToken)‏ +RescueNode #a rescue clause in a def of begin statement | (exceptions: Array[Value*], varname: VarNameToken|nil, action: Value)‏ +WhenNode #a when clause in a case statement | (when: Value|Array[Value+] then: Value|nil )‏ +ElsifNode #an elsif clause in an if statement | (elsif: Value, then: Value|nil)‏ +ValueNode #abstract, a node which has a value (an expression)‏ |+ListOpNode #abstract, ancestor for nodes which are lists of ||| #things separated by some op ||+SequenceNode #a sequence of statements ||| (Array[Value*])‏ ||+ConstantNode #a constant expression of the form A::B::C or the like || #first expression can be anything || (Array[String|Value|nil,String+])‏ |+RawOpNode #ancestor of all operators (but not . :: ; , ?..:)‏ ||| (left: Value, op: String, right: Value)‏ ||+OpNode #ancestor of some operators |||+RangeNode #a range literal node |||+KeywordOpNode #abstract, ancestor of keyword operators ||||+LogicalNode #and or && || expressions ||||+WhileOpNode #while as an operator ||||+UntilOpNode #until as an operator ||||+IfOpNode #if as an operator ||||+UnlessOpNode #unless as an operator |||+NotEqualNode #!= expressions
  • 13. |||+MatchNode #=~ expressions |||+NotMatchNode #!~ expressions |+LiteralNode #literal symbols, integers || (val: Numeric|Symbol|StringNode)‏ |+StringNode #literal strings ||| (Array[(String|Value)+])‏ ||+HereDocNode #here documents |+StringCatNode #adjacent strings are catenated (&quot;foo&quot; &quot;bar&quot; == &quot;foobar&quot;)‏ || (Array[StringNode+])‏ |+NopNode #an expression with no tokens at all in it || (no attributes)‏ |+VarLikeNode #nil,false,true,__FILE__,__LINE__,self || (name: String)‏ |+UnOpNode #unary operators || (op: String, val: Value)‏ ||+UnaryStarNode #unary star (splat)‏ |||+DanglingStarNode #unary star with no argument ||||| (no attributes)‏ ||||+DanglingCommaNode #comma with no rhs || (no attributes)‏ |+ParenedNode #ugly, parenthesized expressions and begin..end || (body: Value) -OR- (parentheses)‏ || (body: Value|nil, rescues: Array[RescueNode*], || else: Value|nil, ensure: Value|nil) (begin...end and rescue as operator)‏ |+AssignNode #assignment (including eg +=)‏ || (left:AssigneeList|LValue, op:String ,right:Array[Value*]|Value)‏
  • 14. |+AssigneeList #abstract, comma-delimited list of assignables ||| (Array[LValue*])‏ ||+NestedAssign #nested lhs, in parentheses ||+MultiAssign #regular top-level lhs ||+BlockParams #block formal parameter list |+CallSiteNode #abstract, method calls ||| (receiver: Value|nil, name: String, ||| params: nil|Array[Value+,UnaryStarNode?,UnAmpNode?], ||| block_params: BlockParams, block: Value)‏ ||+CallNode #normal method calls ||+KWCallNode #keywords that look (more or less) like methods || #(BEGIN END yield return break continue next)‏ |+ArrayLiteralNode #[..] || (Array[Value*])‏ |+IfNode #if..end and unless..end || (if: Value, then: Value|nil, elsifs: Array[ElsifNode+]|Nil, else: Value|nil)‏ |+LoopNode #while..end and until..end || (while: Value, do: Value:nil)‏ |+CaseNode #case..end || (case: Value|nil, whens: Array[WhenNode*], else: Value|nil)‏ |+ForNode #for..end || (for: LValue, in: Value, do: Value|nil)‏ |+HashLiteralNode #{..} || (Array[Value*]) (size must be even)‏ |+TernaryNode # ? .. : || (if: Value, then: Value, else: Value)‏
  • 15. |+MethodNode #def..end || (receiver:Value|nil, name:String, || params:Array[VarNameToken*,AssignNode*,UnaryStarNode?,UnAmpNode?]|nil, || body: Value|nil, rescues: Array[RescueNode+]|nil, else: Value|nil, ensure: Value|nil)‏ |+AliasNode #alias foo bar || (to: String|VarNameToken|StringNode, from: String|VarNameToken|StringNode)‏ |+UndefNode #undef foo || (Array[String|StringNode+])‏ |+NamespaceNode #abstract ||+ModuleNode #module..end ||| (name: VarNameToken|ConstantNode, body: Value|nil)‏ ||+ClassNode #class..end ||| (name: VarNameToken|ConstantNode, parent: Value|nil, body: Value|nil)‏ ||+MetaClassNode #class<<x..end || (val: Value, body: Value|nil)‏ |+BracketsGetNode #a[b] | (receiver: Value, params: Array[Value+,UnaryStarNode?]|nil)‏ | ErrorNode #mixed in to nodes with a syntax error +MisparsedNode #mismatched braces or begin..end or the like
  • 16. Drawbacks: Pre-processing is very, very slow (because of RedParse)‏ Macro calls must be in some sort of method... straight out macros at the top level won't work Macro blocks and receivers aren't supported Some ruby syntax won't work in files using macros Files using macros must be loaded via Macro.require... not normal require RedParse Node tree format will be changing Macros cannot be scoped