Added modulo operator '%'

- added OP_MOD, which performs a modulo operation on the 2 <number> values on the stack. Pops the 2 values and pushes the result.
- also added TOKEN_PERCENT to the lexer, and extended binary() in cparse.c to support it.
This commit is contained in:
CPunch 2021-01-01 00:47:15 -06:00
parent 58485d9375
commit 84f7895684
7 changed files with 22 additions and 1 deletions

View File

@ -2,7 +2,7 @@
CC=clang CC=clang
CFLAGS=-fPIE -Wall -O3 -std=c11 CFLAGS=-fPIE -Wall -O3 -std=c11
LDFLAGS=#-fsanitize=address LDFLAGS=-lm #-fsanitize=address
OUT=bin/cosmo OUT=bin/cosmo
CHDR=\ CHDR=\

View File

@ -144,6 +144,8 @@ int disasmInstr(CChunk *chunk, int offset, int indent) {
return simpleInstruction("OP_MULT", offset); return simpleInstruction("OP_MULT", offset);
case OP_DIV: case OP_DIV:
return simpleInstruction("OP_DIV", offset); return simpleInstruction("OP_DIV", offset);
case OP_MOD:
return simpleInstruction("OP_MOD", offset);
case OP_TRUE: case OP_TRUE:
return simpleInstruction("OP_TRUE", offset); return simpleInstruction("OP_TRUE", offset);
case OP_FALSE: case OP_FALSE:

View File

@ -308,6 +308,7 @@ CToken cosmoL_scanToken(CLexState *state) {
case ',': return makeToken(state, TOKEN_COMMA); case ',': return makeToken(state, TOKEN_COMMA);
case ':': return makeToken(state, TOKEN_COLON); case ':': return makeToken(state, TOKEN_COLON);
case '*': return makeToken(state, TOKEN_STAR); case '*': return makeToken(state, TOKEN_STAR);
case '%': return makeToken(state, TOKEN_PERCENT);
case '#': return makeToken(state, TOKEN_POUND); case '#': return makeToken(state, TOKEN_POUND);
case '/': return makeToken(state, TOKEN_SLASH); case '/': return makeToken(state, TOKEN_SLASH);
// two character tokens // two character tokens

View File

@ -23,6 +23,7 @@ typedef enum {
TOKEN_SLASH, TOKEN_SLASH,
TOKEN_STAR, TOKEN_STAR,
TOKEN_POUND, TOKEN_POUND,
TOKEN_PERCENT,
TOKEN_EOS, // end of statement TOKEN_EOS, // end of statement
// equality operators // equality operators

View File

@ -37,6 +37,7 @@ typedef enum {
OP_SUB, OP_SUB,
OP_MULT, OP_MULT,
OP_DIV, OP_DIV,
OP_MOD,
OP_NOT, OP_NOT,
OP_NEGATE, OP_NEGATE,
OP_COUNT, OP_COUNT,

View File

@ -430,6 +430,7 @@ static void binary(CParseState *pstate, bool canAssign) {
case TOKEN_MINUS: writeu8Chunk(pstate->state, getChunk(pstate), OP_SUB, cachedLine); break; case TOKEN_MINUS: writeu8Chunk(pstate->state, getChunk(pstate), OP_SUB, cachedLine); break;
case TOKEN_STAR: writeu8Chunk(pstate->state, getChunk(pstate), OP_MULT, cachedLine); break; case TOKEN_STAR: writeu8Chunk(pstate->state, getChunk(pstate), OP_MULT, cachedLine); break;
case TOKEN_SLASH: writeu8Chunk(pstate->state, getChunk(pstate), OP_DIV, cachedLine); break; case TOKEN_SLASH: writeu8Chunk(pstate->state, getChunk(pstate), OP_DIV, cachedLine); break;
case TOKEN_PERCENT: writeu8Chunk(pstate->state, getChunk(pstate), OP_MOD, cachedLine); break;
// EQUALITY // EQUALITY
case TOKEN_EQUAL_EQUAL: writeu8Chunk(pstate->state, getChunk(pstate), OP_EQUAL, cachedLine); break; case TOKEN_EQUAL_EQUAL: writeu8Chunk(pstate->state, getChunk(pstate), OP_EQUAL, cachedLine); break;
case TOKEN_GREATER: writeu8Chunk(pstate->state, getChunk(pstate), OP_GREATER, cachedLine); break; case TOKEN_GREATER: writeu8Chunk(pstate->state, getChunk(pstate), OP_GREATER, cachedLine); break;
@ -730,6 +731,7 @@ ParseRule ruleTable[] = {
[TOKEN_PLUS_PLUS] = {preincrement, NULL, PREC_TERM}, [TOKEN_PLUS_PLUS] = {preincrement, NULL, PREC_TERM},
[TOKEN_SLASH] = {NULL, binary, PREC_FACTOR}, [TOKEN_SLASH] = {NULL, binary, PREC_FACTOR},
[TOKEN_STAR] = {NULL, binary, PREC_FACTOR}, [TOKEN_STAR] = {NULL, binary, PREC_FACTOR},
[TOKEN_PERCENT] = {NULL, binary, PREC_FACTOR},
[TOKEN_POUND] = {unary, NULL, PREC_NONE}, [TOKEN_POUND] = {unary, NULL, PREC_NONE},
[TOKEN_EOS] = {NULL, NULL, PREC_NONE}, [TOKEN_EOS] = {NULL, NULL, PREC_NONE},
[TOKEN_BANG] = {unary, NULL, PREC_NONE}, [TOKEN_BANG] = {unary, NULL, PREC_NONE},

View File

@ -6,6 +6,8 @@
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#include <math.h>
COSMO_API void cosmoV_pushFString(CState *state, const char *format, ...) { COSMO_API void cosmoV_pushFString(CState *state, const char *format, ...) {
va_list args; va_list args;
va_start(args, format); va_start(args, format);
@ -802,6 +804,18 @@ int cosmoV_execute(CState *state) {
NUMBEROP(cosmoV_newNumber, /) NUMBEROP(cosmoV_newNumber, /)
break; break;
} }
case OP_MOD: {
StkPtr valA = cosmoV_getTop(state, 1);
StkPtr valB = cosmoV_getTop(state, 0);
if (IS_NUMBER(*valA) && IS_NUMBER(*valB)) {
cosmoV_setTop(state, 2); /* pop the 2 values */
cosmoV_pushValue(state, cosmoV_newNumber(fmod(cosmoV_readNumber(*valA), cosmoV_readNumber(*valB))));
} else { \
cosmoV_error(state, "Expected numbers, got %s and %s!", cosmoV_typeStr(*valA), cosmoV_typeStr(*valB));
return -1; \
} \
break;
}
case OP_NOT: { case OP_NOT: {
cosmoV_pushBoolean(state, isFalsey(cosmoV_pop(state))); cosmoV_pushBoolean(state, isFalsey(cosmoV_pop(state)));
break; break;