Skip to content

Commit

Permalink
Implement import and native commands
Browse files Browse the repository at this point in the history
- `import`: imports the given `.h` file into the generated code;
- `native`:  directly calls a `C` language function.

Merge pull request #76 from haroldo-ok/native-command

This fixes #48
  • Loading branch information
haroldo-ok committed Nov 2, 2022
2 parents ee5445d + f25cbed commit 5173994
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 6 deletions.
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,36 @@ Sets the author of the story. Used to populate the ROM headers.
* author "John Doe"
```
### `import`
Imports the given `.h` file into the generated code. Useful when combined with the `native` command.
#### Positional parameters:
* `fileName`: The name of the `.h` file.
#### Example
```shell
* import "extra.h"
```
Will import "extra.h" into the generated `C` file.
### `native`
Directly calls a `C` language function.
#### Positional parameters:
* `functionName`: The name of the `C` function to call.
#### Variadic parameters:
All the positional parameters after `functionName` are passed as parameters to the function.
#### Named parameters:
* `into(variable)` if informed, will update the given variable with the return of the callsed function.
#### Example
```shell
* native addExample, currentTick, 1 + 2, into(functionResult)
```
Will call the function `addExample` passing as parameters the value of the variable `currentTick` and the result of `1 + 2`; the result of the function will be stored in the `functionResult` variable.
## Planned commands
Expand Down
2 changes: 1 addition & 1 deletion base/src/vn_engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ void VN_init() {
XGM_setLoopNumber(-1);
XGM_setForceDelayDMA(TRUE);

VDP_drawText("choice4genesis v0.9.1", 18, 27);
VDP_drawText("choice4genesis v0.10.0", 17, 27);
}


Expand Down
5 changes: 5 additions & 0 deletions examples/test/project/src/extra.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include "extra.h"

int addExample(int a, int b) {
return a + b;
}
6 changes: 6 additions & 0 deletions examples/test/project/src/extra.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef _EXTRA_H_
#define _EXTRA_H_

extern int addExample(int a, int b);

#endif /* _EXTRA_H_ */
8 changes: 8 additions & 0 deletions examples/test/project/startup.choice
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,13 @@
Yet another line.
A really, really long line, to test a bit more.
Final line.
# Test native calls
* import "extra.h"
* temp currentTick, 0
* temp functionResult, 0
* native getTick, into(currentTick)
* native addExample, currentTick, 1 + 2, into(functionResult)
Current tick is ${currentTick}
Second function result is ${functionResult}
# Go to another scene
* goto_scene test
30 changes: 29 additions & 1 deletion generator/generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,33 @@ const COMMAND_GENERATORS = {
context.header.author = name;
return null;
},

'import': (entity, context) => {
const fileName = getStringConstant(entity, entity.params.positional.fileName, context, 'File name');
context.imports.push(fileName);
return null;
},

'native': (entity, context) => {
const functionName = getIdentifier(entity, entity.params.positional.functionName, context, 'Function name');

let assignment = '';
const named = entity.params.named || {};
if (named.into) {
const varName = getIdentifier(entity, named.into.variable, context, 'Variable name');
const existingVar = context.locals.get(varName) || context.globals.get(varName);
if (existingVar) {
assignment = `${existingVar.value.internalVar} = `;
} else {
context.errors.push(buildEntityError(entity, `Couldn't find a variable named "${varName}".`));
}
}

const parameters = (entity.params.variadic || []).map((param, index) =>
getExpression(entity, param, context, `Parameter ${index + 1}`) || {});

return `${assignment}${functionName}(${parameters.map(expression => expression.code).join(', ')});`;
}
};


Expand Down Expand Up @@ -463,7 +490,7 @@ const generateFromSource = (mainSourceName, context) => {
return {
sources: {
'generated_scripts.c': [
'#include "vn_engine.h"',
['vn_engine.h', ...context.imports].map(fileName => `#include "${fileName}"`).join('\n'),
generateVariableDeclarations(context.globals),
generatedForwards.join('\n'),
...generatedFunctions
Expand All @@ -487,6 +514,7 @@ const generate = fileSystem => {
choices: [],
globals: createNamespace(),
locals: null,
imports: [],
header: {
author: 'Unnamed Author',
title: 'Unnamed Story'
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "choice4genesis",
"version": "0.9.1",
"version": "0.10.0",
"description": "A ChoiceScript clone that generates SGDK-compatible C source for the Sega Genesis ",
"main": "index.js",
"scripts": {
Expand Down
11 changes: 9 additions & 2 deletions parser/expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,18 @@ const buildResultObject = (result, lineNumber, config) => {
const errors = [];
const params = {};

const positional = collectPositionalArguments(result.value, config.positional, errors);
validateTooManyArguments(result.value, config.positional, errors);
const positional = collectPositionalArguments(result.value, config.positional, errors);
const variadic = config.variadic ? (result.value || []).slice(positional.length).filter(param => param[0] !== 'NamedParam') : [];

if (!config.variadic) {
validateTooManyArguments(result.value, config.positional, errors);
}
if (positional.length) {
params.positional = Object.fromEntries(positional);
}
if (variadic.length) {
params.variadic = variadic;
}

const flags = collectFlags(result, config, errors);
if (flags.length) {
Expand Down
5 changes: 4 additions & 1 deletion parser/syntax-full.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ const COMMANDS = {

'choice': { },
'scene_list': { },
'finish': { }
'finish': { },

'import': { positional: ['fileName'] },
'native': { positional: ['functionName'], named: { into: ['variable'] }, variadic: true }
};

const COMMAND_PARSERS = Object.fromEntries(Object.entries(COMMANDS).map(([command, config]) => [command, createExpressionParser(config)]));
Expand Down

0 comments on commit 5173994

Please sign in to comment.