*/
#include <string.h>
#include <math.h>
+
#include "parser.h"
#define PARSER_HT_LOCALS 2
#define NotSameType(T) \
(exprs[0]->vtype != exprs[1]->vtype || \
exprs[0]->vtype != T)
+
switch (op->id)
{
default:
out = exprs[0];
break;
case opid2('-','P'):
- if (!(out = fold_op(parser->fold, op, exprs))) {
- switch (exprs[0]->vtype) {
- case TYPE_FLOAT:
- out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F,
- (ast_expression*)parser->fold->imm_float[0],
- exprs[0]);
- break;
- case TYPE_VECTOR:
- out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V,
- (ast_expression*)parser->fold->imm_vector[0],
- exprs[0]);
- break;
- default:
- compile_error(ctx, "invalid types used in expression: cannot negate type %s",
+ if ((out = fold_op(parser->fold, op, exprs)))
+ break;
+
+ if (exprs[0]->vtype != TYPE_FLOAT &&
+ exprs[0]->vtype != TYPE_VECTOR) {
+ compile_error(ctx, "invalid types used in unary expression: cannot negate type %s",
type_name[exprs[0]->vtype]);
- return false;
- }
+ return false;
}
+ out = (ast_expression*)ast_unary_new(ctx, (VINSTR_NEG_F-TYPE_FLOAT) + exprs[0]->vtype, exprs[0]);
break;
case opid2('!','P'):
out = (ast_expression*)ast_binary_new(ctx, subop,
out,
(ast_expression*)parser->fold->imm_float[1]);
+
break;
case opid2('+','='):
case opid2('-','='):
* sy->out should I be doing here?
*/
sy->out[fid] = syexp(foldval->node.context, foldval);
- vec_shrinkby(sy->out, 1);
+ vec_shrinkby(sy->out, paramcount);
vec_free(exprs);
return true;
return false;
}
}
+ else if (!strcmp(parser_tokval(parser), "accumulate")) {
+ flags |= AST_FLAG_ACCUMULATE;
+ if (!parser_next(parser) || parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
+ parseerror(parser, "`accumulate` attribute has no parameters, expected `]]`");
+ *cvq = CV_WRONG;
+ return false;
+ }
+ }
else if (!strcmp(parser_tokval(parser), "alias") && !(flags & AST_FLAG_ALIAS)) {
flags |= AST_FLAG_ALIAS;
*message = NULL;
else
{
(void)!parsewarning(parser, WARN_UNKNOWN_PRAGMAS, "ignoring #pragma %s", parser_tokval(parser));
- return false;
+
+ /* skip to eol */
+ while (!parse_eol(parser)) {
+ parser_next(parser);
+ }
+
+ return true;
}
return true;
if (parser->tok == TOKEN_IDENT)
typevar = parser_find_typedef(parser, parser_tokval(parser), 0);
- if (typevar || parser->tok == TOKEN_TYPENAME || parser->tok == '.')
+ if (typevar || parser->tok == TOKEN_TYPENAME || parser->tok == '.' || parser->tok == TOKEN_DOTS)
{
/* local variable */
if (!block) {
}
}
- if (var->hasvalue) {
+ if (var->hasvalue && !(var->expression.flags & AST_FLAG_ACCUMULATE)) {
parseerror(parser, "function `%s` declared with multiple bodies", var->name);
ast_block_delete(block);
goto enderr;
}
- func = ast_function_new(ast_ctx(var), var->name, var);
+ /* accumulation? */
+ if (var->hasvalue) {
+ ast_value *accum = NULL;
+ ast_function *previous = NULL;
+ char acname[1024];
+
+ /* generate a new name increasing the accumulation count*/
+ util_snprintf(acname, sizeof(acname), "$ACCUMULATE_%s_%d", var->name, var->constval.vfunc->accumulation++);
+ accum = ast_value_new(parser_ctx(parser), acname, ((ast_expression*)var)->vtype);
+ if (!accum)
+ return false;
+
+ ast_type_adopt(accum, var);
+ func = ast_function_new(ast_ctx(var), NULL, accum);
+ if (!func)
+ return false;
+
+ parser_addglobal(parser, acname, (ast_expression*)accum);
+ vec_push(parser->functions, func);
+
+ /* update the previous calls accumulate pointer for the codegen */
+ previous = var->constval.vfunc;
+ while (previous->accumulate)
+ previous = previous->accumulate;
+
+ if (ast_istype(previous, ast_function))
+ previous->accumulate = func;
+
+ } else {
+ func = ast_function_new(ast_ctx(var), var->name, var);
+ vec_push(parser->functions, func);
+ }
+
if (!func) {
parseerror(parser, "failed to allocate function for `%s`", var->name);
ast_block_delete(block);
goto enderr;
}
- vec_push(parser->functions, func);
parser_enterblock(parser);
ctx = parser_ctx(parser);
/* types may start with a dot */
- if (parser->tok == '.') {
+ if (parser->tok == '.' || parser->tok == TOKEN_DOTS) {
isfield = true;
+ if (parser->tok == TOKEN_DOTS)
+ morefields += 2;
/* if we parsed a dot we need a typename now */
if (!parser_next(parser)) {
parseerror(parser, "expected typename for field definition");
/* Further dots are handled seperately because they won't be part of the
* basetype
*/
- while (parser->tok == '.') {
- ++morefields;
+ while (true) {
+ if (parser->tok == '.')
+ ++morefields;
+ else if (parser->tok == TOKEN_DOTS)
+ morefields += 3;
+ else
+ break;
if (!parser_next(parser)) {
parseerror(parser, "expected typename for field definition");
return NULL;
var->expression.flags & AST_FLAG_ALIAS)
var->desc = vstring;
+ if (parser_find_global(parser, var->name) && var->expression.flags & AST_FLAG_ALIAS) {
+ parseerror(parser, "function aliases cannot be forward declared");
+ retval = false;
+ goto cleanup;
+ }
+
+
/* Part 1:
* check for validity: (end_sys_..., multiple-definitions, prototypes, ...)
* Also: if there was a prototype, `var` will be deleted and set to `proto` which
return false;
}
- if (var->expression.vtype != find->vtype) {
+ if (!ast_compare_type((ast_expression*)var, find)) {
char ty1[1024];
char ty2[1024];
if (parser->tok == TOKEN_IDENT)
istype = parser_find_typedef(parser, parser_tokval(parser), 0);
- if (istype || parser->tok == TOKEN_TYPENAME || parser->tok == '.')
+ if (istype || parser->tok == TOKEN_TYPENAME || parser->tok == '.' || parser->tok == TOKEN_DOTS)
{
return parse_variable(parser, NULL, false, CV_NONE, istype, false, false, 0, NULL);
}
}
}
if (!parser->assign_op) {
- printf("internal error: initializing parser: failed to find assign operator\n");
+ con_err("internal error: initializing parser: failed to find assign operator\n");
mem_d(parser);
return NULL;
}