Re: Adding a new builtin function

new topic     » goto parent     » topic index » view thread      » older message » newer message
Jerome said...

I started grepping through the source code today in an attempt to add a new builtin function. For example, I want to add a simple function that takes 1 input (atom) and returns 1 output (atom): atom foo(atom a). I found some tips/instructions in the source files, but I'm missing some key steps. In reswors.h it says:

  remember to update reswords.e, opnames.e, 
   opnames.h, optable[], localjumptab[] 
   in be_execute.c, be_runtime.c. redef.h, 
   emit.e, keylist.e, compile.e, be_syncolor.c 

I think we need to update the hints. You'll also definitely need to update shift.e.

Jerome said...
Fatal run-time error: 
BAD IL OPCODE: i is 4, word is 1590060 (max=12), len is 1076948992 

The error occurs in the function code_set_pointers in be_execute.c. Any suggestions?

This error suggests that when the previous opcode was dealt with, i was incremented by an incorrect amount. I'm not sure what "max" is supposed to be (I suspect MAX_OPCODE), but it's being reported with the value for len. The statement is clearly wrong:

 
if (word > MAX_OPCODE || word < 1) { 
	RTFatal("BAD IL OPCODE: i is %d, word is %d (max=%d), len is %d", 
			i, word, len); 
} 

When we parse euphoria code, everything is represented as indices into the symbol table, which is just a sequence in the front end. When your code is actually executed by the back end, however, pointers are much more efficient. This function converts the indices into pointers (the symbol table is converted from a sequence to the corresponding C struct in backend.e).

We use the macro, SET_OPERAND() to translate from an index into the symbol table to a pointer to the correct symtab entry struct, and SET_JUMP() to translate from an index pointing to a particular point in the IL code to where that instruction is in memory.

Different opcodes have different numbers and types of arguments, of course, though many share these characteristics with each other, as you'll notice the groupings of the various opcodes. When you create a new built-in, you have to put yours in the appropriate place or write a customized version if you need to.

There are a lot of places that need to be updated when you add a built-in. I recommend updating dis.e so that you can take a look at the generated IL code to make sure the front end is working correctly. Assuming you're adding foo() to be similar to cos(), you would just need to add the following to dis.e:

procedure opFOO() 
	unary() 
end procedure 

We should really document this whole process better. Maybe a wiki page.

Matt

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu