Anders Rune Jensen
Anders Rune Jensen

Reputation: 3806

How can I simulate macros in JavaScript?

I know that JavaScript doesn't support macros (Lisp-style ones) but I was wondering if anyone had a solution to maybe simulate macros? I Googled it, and one of the solutions suggested using eval(), but as he said, would be quite costly.

They don't really have to be very fancy. I just want to do simple stuff with them. And it shouldn't make debugging significantly harder :)

Upvotes: 33

Views: 37812

Answers (9)

user26818679
user26818679

Reputation: 1

I'd like to mention a hack to get somewhat like macros in js (that can be used only inside a function), that also work quite well with autocompletion.

let's suppose that we have somewhere defined our macro like this

DefMacro("unless", (params, body) => `
if(!(${params})) {
    ${body}
}`);

now let's suppose we have created function MacroFunction, that converts input function to string, and creates new function recursively replacing patterns like !macroName(params), () => {body}, with predefined macros, and casting it to new function using Function object (should have same optimisations as normal function, because each function is Function)

MacroFunction(() => {
  let x = true;
  !unless(x),  () => {
      return x;
  }
});

so we have given the valid javascript syntax different semantics, that behaves like our macro

Upvotes: 0

Blake McBride
Blake McBride

Reputation: 412

Check out the Linux/Unix/GNU M4 processor. It is a generic and powerful macro processor for any language. It is especially oriented towards Algol-style languages of which JavaScript is a member.

Upvotes: 0

Anderson Green
Anderson Green

Reputation: 31840

A library by Mozilla (called SweetJS) is designed to simulate macros in JavaScript. For example, you can use SweetJS to replace the function keyword with def.

Upvotes: 28

Santosh
Santosh

Reputation: 1958

LispyScript is the latest language that compiles to Javascript, that supports macros. It has a Lisp like tree syntax, but also maintains the same Javascript semantics. Disclaimer: I am the author of LispyScript.

Upvotes: 4

Anders Rune Jensen
Anders Rune Jensen

Reputation: 3806

One can also now use ClojureScript to compile clojure to javascript and get macros that way. Note ClojureScript uses Google Closure.

Upvotes: 12

Volodymyr M. Lisivka
Volodymyr M. Lisivka

Reputation: 142

function unless(condition,body) {
    return 'if(! '+condition.toSource()+'() ) {' + body.toSource()+'(); }';
}


eval(unless( function() {
    return false;
  }, function() {
    alert("OK");
}));

Upvotes: 7

Pedro Ladaria
Pedro Ladaria

Reputation:

I've written a gameboy emulator in javascript and I simulate macros for cpu emulation this way:

macro code (the function returns a string with the macro code):

function CPU_CP_A(R,C) { // this function simulates the CP instruction, 
  return ''+             // sets CPU flags and stores in CCC the number
  'FZ=(RA=='+R+');'+     // of cpu cycles needed
  'FN=1;'+
  'FC=RA<'+R+';'+
  'FH=(RA&0x0F)<('+R+'&0x0F);'+
  'ICC='+C+';';
}

Using the "macro", so the code is generated "on the fly" and we don't need to make function calls to it or write lots of repeated code for each istruction...

OP[0xB8]=new Function(CPU_CP_A('RB',4)); // CP B
OP[0xB9]=new Function(CPU_CP_A('RC',4)); // CP C
OP[0xBA]=new Function(CPU_CP_A('RD',4)); // CP D
OP[0xBB]=new Function(CPU_CP_A('RE',4)); // CP E
OP[0xBC]=new Function('T1=HL>>8;'+CPU_CP_A('T1',4)); // CP H
OP[0xBD]=new Function('T1=HL&0xFF;'+CPU_CP_A('T1',4)); // CP L
OP[0xBE]=new Function('T1=MEM[HL];'+CPU_CP_A('T1',8)); // CP (HL)
OP[0xBF]=new Function(CPU_CP_A('RA',4)); // CP A

Now we can execute emulated code like this:

OP[MEM[PC]](); // MEM is an array of bytes and PC the program counter

Hope it helps...

Upvotes: 9

Lu&#237;s Oliveira
Lu&#237;s Oliveira

Reputation: 2974

You could use parenscript. That'll give you macros for Javascript.

Upvotes: 29

James Curran
James Curran

Reputation: 103535

Javascript is interpreted. Eval isn't any more costly that anything else in Javascript.

Upvotes: -1

Related Questions