ADD: strings.
parent
2daf39240a
commit
6013d65776
|
@ -17,7 +17,54 @@ void compile_node(compiler* self, node* root, program* prog)
|
||||||
assert(root);
|
assert(root);
|
||||||
assert(prog);
|
assert(prog);
|
||||||
|
|
||||||
if (root->type == NODE_BOOLEAN)
|
if (root->type == NODE_MUL)
|
||||||
|
{
|
||||||
|
cstatic cs;
|
||||||
|
cstatic_init(&cs);
|
||||||
|
|
||||||
|
int lhs = cstatic_resolve(&cs, root->children.data[0]);
|
||||||
|
int rhs = cstatic_resolve(&cs, root->children.data[1]);
|
||||||
|
|
||||||
|
cstatic_free(&cs);
|
||||||
|
|
||||||
|
if (lhs == TY_INTEGER && rhs == TY_STRING)
|
||||||
|
{
|
||||||
|
compile_node(self, root->children.data[0], prog);
|
||||||
|
compile_node(self, root->children.data[1], prog);
|
||||||
|
program_add_instr(prog, OP_SMUL, NO_PARAM);
|
||||||
|
}
|
||||||
|
else if (lhs == TY_STRING && rhs == TY_INTEGER)
|
||||||
|
{
|
||||||
|
compile_node(self, root->children.data[1], prog);
|
||||||
|
compile_node(self, root->children.data[0], prog);
|
||||||
|
program_add_instr(prog, OP_SMUL, NO_PARAM);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
compile_number(self, root, prog, OP_IMUL, OP_FMUL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (root->type == NODE_ADD)
|
||||||
|
{
|
||||||
|
cstatic cs;
|
||||||
|
cstatic_init(&cs);
|
||||||
|
|
||||||
|
int lhs = cstatic_resolve(&cs, root->children.data[0]);
|
||||||
|
int rhs = cstatic_resolve(&cs, root->children.data[1]);
|
||||||
|
|
||||||
|
cstatic_free(&cs);
|
||||||
|
|
||||||
|
if (lhs == rhs && lhs == TY_STRING)
|
||||||
|
{
|
||||||
|
compile_children(self, root, prog);
|
||||||
|
program_add_instr(prog, OP_CAT, NO_PARAM);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
compile_number(self, root, prog, OP_IADD, OP_FADD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (root->type == NODE_BOOLEAN)
|
||||||
{
|
{
|
||||||
value val;
|
value val;
|
||||||
value_init_boolean(&val,
|
value_init_boolean(&val,
|
||||||
|
@ -37,6 +84,16 @@ void compile_node(compiler* self, node* root, program* prog)
|
||||||
program_add_instr(prog, OP_PUSH, idx);
|
program_add_instr(prog, OP_PUSH, idx);
|
||||||
value_free(&val);
|
value_free(&val);
|
||||||
}
|
}
|
||||||
|
else if (root->type == NODE_STRING)
|
||||||
|
{
|
||||||
|
value val;
|
||||||
|
value_init_string(&val,
|
||||||
|
root->value,
|
||||||
|
root->lineno);
|
||||||
|
size_t idx = program_add_pool(prog, &val);
|
||||||
|
program_add_instr(prog, OP_PUSH, idx);
|
||||||
|
value_free(&val);
|
||||||
|
}
|
||||||
else if (root->type == NODE_INTEGER)
|
else if (root->type == NODE_INTEGER)
|
||||||
{
|
{
|
||||||
value val;
|
value val;
|
||||||
|
@ -60,10 +117,6 @@ void compile_node(compiler* self, node* root, program* prog)
|
||||||
{
|
{
|
||||||
compile_number(self, root, prog, OP_IUSUB, OP_FUSUB);
|
compile_number(self, root, prog, OP_IUSUB, OP_FUSUB);
|
||||||
}
|
}
|
||||||
else if (root->type == NODE_ADD)
|
|
||||||
{
|
|
||||||
compile_number(self, root, prog, OP_IADD, OP_FADD);
|
|
||||||
}
|
|
||||||
else if (root->type == NODE_SUB)
|
else if (root->type == NODE_SUB)
|
||||||
{
|
{
|
||||||
compile_number(self, root, prog, OP_ISUB, OP_FSUB);
|
compile_number(self, root, prog, OP_ISUB, OP_FSUB);
|
||||||
|
|
|
@ -16,6 +16,17 @@ int cstatic_resolve(cstatic* self, node* ast)
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(ast);
|
assert(ast);
|
||||||
|
|
||||||
|
if (ast->type == NODE_MUL)
|
||||||
|
{
|
||||||
|
int lhs = cstatic_resolve(self, ast->children.data[0]);
|
||||||
|
int rhs = cstatic_resolve(self, ast->children.data[1]);
|
||||||
|
|
||||||
|
if (lhs == TY_STRING || rhs == TY_STRING)
|
||||||
|
{
|
||||||
|
return TY_STRING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ast->type == NODE_INTEGER)
|
if (ast->type == NODE_INTEGER)
|
||||||
{
|
{
|
||||||
return TY_INTEGER;
|
return TY_INTEGER;
|
||||||
|
@ -24,6 +35,25 @@ int cstatic_resolve(cstatic* self, node* ast)
|
||||||
{
|
{
|
||||||
return TY_FLOAT;
|
return TY_FLOAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (ast->type == NODE_ADD)
|
||||||
|
{
|
||||||
|
int lhs = cstatic_resolve(self, ast->children.data[0]);
|
||||||
|
int rhs = cstatic_resolve(self, ast->children.data[1]);
|
||||||
|
|
||||||
|
if (lhs == TY_STRING && rhs == TY_STRING)
|
||||||
|
{
|
||||||
|
return TY_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (ast->type == NODE_STRING)
|
||||||
|
{
|
||||||
|
return TY_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
else if (ast->type == NODE_BOOLEAN
|
else if (ast->type == NODE_BOOLEAN
|
||||||
|| ast->type == NODE_EQ
|
|| ast->type == NODE_EQ
|
||||||
|| ast->type == NODE_NE)
|
|| ast->type == NODE_NE)
|
||||||
|
@ -64,6 +94,31 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String Operations
|
||||||
|
if (ast->type == NODE_ADD)
|
||||||
|
{
|
||||||
|
int lhs = cstatic_resolve(self, ast->children.data[0]);
|
||||||
|
int rhs = cstatic_resolve(self, ast->children.data[1]);
|
||||||
|
|
||||||
|
|
||||||
|
if (lhs == rhs && lhs == TY_STRING)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ast->type == NODE_MUL)
|
||||||
|
{
|
||||||
|
int lhs = cstatic_resolve(self, ast->children.data[0]);
|
||||||
|
int rhs = cstatic_resolve(self, ast->children.data[1]);
|
||||||
|
|
||||||
|
if ((lhs == TY_STRING && rhs == TY_INTEGER)
|
||||||
|
|| (lhs == TY_INTEGER && rhs == TY_STRING))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Integer Binops
|
// Integer Binops
|
||||||
if (ast->type == NODE_EQ
|
if (ast->type == NODE_EQ
|
||||||
|| ast->type == NODE_NE)
|
|| ast->type == NODE_NE)
|
||||||
|
@ -140,7 +195,6 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Integer Binops
|
// Integer Binops
|
||||||
else if (ast->type == NODE_ADD
|
else if (ast->type == NODE_ADD
|
||||||
|| ast->type == NODE_SUB
|
|| ast->type == NODE_SUB
|
||||||
|
|
|
@ -12,6 +12,7 @@ WHITESPACES [ \t]+
|
||||||
BOOLEAN true|false
|
BOOLEAN true|false
|
||||||
INTEGER -?[0-9]+
|
INTEGER -?[0-9]+
|
||||||
FLOAT -?[0-9]+\.[0-9]+
|
FLOAT -?[0-9]+\.[0-9]+
|
||||||
|
STRING \"[^\"]*\"
|
||||||
|
|
||||||
%%
|
%%
|
||||||
"\n" { line++; }
|
"\n" { line++; }
|
||||||
|
@ -39,6 +40,11 @@ FLOAT -?[0-9]+\.[0-9]+
|
||||||
return BOOLEAN;
|
return BOOLEAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{STRING} {
|
||||||
|
yylval.str = yytext;
|
||||||
|
return STRING;
|
||||||
|
}
|
||||||
|
|
||||||
{FLOAT} {
|
{FLOAT} {
|
||||||
yylval.str = yytext;
|
yylval.str = yytext;
|
||||||
return FLOAT;
|
return FLOAT;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#define NODE_TYPE(G) \
|
#define NODE_TYPE(G) \
|
||||||
G(NODE_PROG), \
|
G(NODE_PROG), \
|
||||||
G(NODE_BOOLEAN), G(NODE_INTEGER), G(NODE_FLOAT), \
|
G(NODE_BOOLEAN), G(NODE_INTEGER), G(NODE_FLOAT), \
|
||||||
|
G(NODE_STRING), \
|
||||||
G(NODE_AND), G(NODE_OR), G(NODE_NOT), \
|
G(NODE_AND), G(NODE_OR), G(NODE_NOT), \
|
||||||
G(NODE_EQ), G(NODE_NE), \
|
G(NODE_EQ), G(NODE_NE), \
|
||||||
G(NODE_ASSERT), \
|
G(NODE_ASSERT), \
|
||||||
|
|
|
@ -25,7 +25,9 @@
|
||||||
G(OP_FMOD), \
|
G(OP_FMOD), \
|
||||||
G(OP_FPOW), \
|
G(OP_FPOW), \
|
||||||
G(OP_FUADD), \
|
G(OP_FUADD), \
|
||||||
G(OP_FUSUB),
|
G(OP_FUSUB), \
|
||||||
|
G(OP_CAT), \
|
||||||
|
G(OP_SMUL)
|
||||||
|
|
||||||
enum Opcodes {
|
enum Opcodes {
|
||||||
OPCODES(GEN_ENUM)
|
OPCODES(GEN_ENUM)
|
||||||
|
|
12
src/parser.y
12
src/parser.y
|
@ -22,7 +22,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
%left ASSERT
|
%left ASSERT
|
||||||
%token <str> BOOLEAN INTEGER FLOAT
|
%token <str> BOOLEAN INTEGER FLOAT STRING
|
||||||
%left EQ NE
|
%left EQ NE
|
||||||
%left AND
|
%left AND
|
||||||
%left OR
|
%left OR
|
||||||
|
@ -166,6 +166,16 @@ expr:
|
||||||
$$ = $2;
|
$$ = $2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
| STRING {
|
||||||
|
node* n = malloc(sizeof(node));
|
||||||
|
size_t const SZ = strlen($1);
|
||||||
|
char str[SZ - 2];
|
||||||
|
memcpy(str, $1 + 1, SZ - 2);
|
||||||
|
str[SZ - 2] = '\0';
|
||||||
|
|
||||||
|
node_init(n, NODE_STRING, str, line);
|
||||||
|
$$ = n;
|
||||||
|
}
|
||||||
|
|
||||||
| BOOLEAN {
|
| BOOLEAN {
|
||||||
node* n = malloc(sizeof(node));
|
node* n = malloc(sizeof(node));
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
G(TY_BOOLEAN), \
|
G(TY_BOOLEAN), \
|
||||||
G(TY_INTEGER), \
|
G(TY_INTEGER), \
|
||||||
G(TY_FLOAT), \
|
G(TY_FLOAT), \
|
||||||
|
G(TY_STRING), \
|
||||||
G(TY_TYPE_COUNT)
|
G(TY_TYPE_COUNT)
|
||||||
|
|
||||||
enum Types {
|
enum Types {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
char const* str_new(char const* str)
|
char* str_new(char const* str)
|
||||||
{
|
{
|
||||||
size_t len = strlen(str) + 1;
|
size_t len = strlen(str) + 1;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#ifndef UTILS_H
|
#ifndef UTILS_H
|
||||||
#define UTILS_H
|
#define UTILS_H
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
char const* str_new(char const* str);
|
char* str_new(char const* str);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
34
src/value.c
34
src/value.c
|
@ -30,9 +30,29 @@ void value_init_float(value* self, float real_float, int lineno)
|
||||||
type_init(self->type, TY_FLOAT);
|
type_init(self->type, TY_FLOAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void value_init_string(value* self, char* str, int lineno)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
self->val.string = str_new(str);
|
||||||
|
|
||||||
|
self->lineno = lineno;
|
||||||
|
|
||||||
|
self->type = malloc(sizeof(type));
|
||||||
|
type_init(self->type, TY_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
void value_free(value* self)
|
void value_free(value* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
|
if (self->type->base_type == TY_STRING
|
||||||
|
&& self->val.string != NULL)
|
||||||
|
{
|
||||||
|
free(self->val.string);
|
||||||
|
self->val.string = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
type_free(self->type);
|
type_free(self->type);
|
||||||
free(self->type);
|
free(self->type);
|
||||||
self->type = NULL;
|
self->type = NULL;
|
||||||
|
@ -44,6 +64,12 @@ value* value_new_clone(value* self)
|
||||||
value* clone = malloc(sizeof(value));
|
value* clone = malloc(sizeof(value));
|
||||||
clone->type = type_new_clone(self->type);
|
clone->type = type_new_clone(self->type);
|
||||||
clone->val = self->val;
|
clone->val = self->val;
|
||||||
|
|
||||||
|
if (self->type->base_type == TY_STRING)
|
||||||
|
{
|
||||||
|
clone->val.string = str_new(self->val.string);
|
||||||
|
}
|
||||||
|
|
||||||
clone->lineno = self->lineno;
|
clone->lineno = self->lineno;
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
|
@ -75,6 +101,11 @@ int value_equals(value* self, value* rhs)
|
||||||
return self->val.real_float == rhs->val.real_float;
|
return self->val.real_float == rhs->val.real_float;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self->type->base_type == TY_STRING)
|
||||||
|
{
|
||||||
|
return strcmp(self->val.string, rhs->val.string) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
size_t const SZ = 512;
|
size_t const SZ = 512;
|
||||||
char ty_str[SZ];
|
char ty_str[SZ];
|
||||||
|
|
||||||
|
@ -95,6 +126,9 @@ size_t value_str(value* self, char* buffer, size_t size)
|
||||||
return snprintf(buffer, size, "%s",
|
return snprintf(buffer, size, "%s",
|
||||||
self->val.boolean == 0
|
self->val.boolean == 0
|
||||||
? "false" : "true");
|
? "false" : "true");
|
||||||
|
case TY_STRING:
|
||||||
|
return snprintf(buffer, size, "%s",
|
||||||
|
self->val.string);
|
||||||
case TY_INTEGER:
|
case TY_INTEGER:
|
||||||
return snprintf(buffer, size, "%d",
|
return snprintf(buffer, size, "%d",
|
||||||
self->val.integer);
|
self->val.integer);
|
||||||
|
|
|
@ -11,12 +11,15 @@ typedef struct {
|
||||||
int boolean;
|
int boolean;
|
||||||
int integer;
|
int integer;
|
||||||
float real_float;
|
float real_float;
|
||||||
|
char* string;
|
||||||
} val;
|
} val;
|
||||||
} value;
|
} value;
|
||||||
|
|
||||||
void value_init_boolean(value* self, int boolean, int lineno);
|
void value_init_boolean(value* self, int boolean, int lineno);
|
||||||
void value_init_integer(value* self, int integer, int lineno);
|
void value_init_integer(value* self, int integer, int lineno);
|
||||||
void value_init_float(value* self, float real_float, int lineno);
|
void value_init_float(value* self, float real_float, int lineno);
|
||||||
|
void value_init_string(value* self, char* string, int lineno);
|
||||||
|
|
||||||
void value_free(value* self);
|
void value_free(value* self);
|
||||||
|
|
||||||
value* value_new_clone(value* self);
|
value* value_new_clone(value* self);
|
||||||
|
|
64
src/vm.c
64
src/vm.c
|
@ -65,6 +65,10 @@ void vm_exec(vm* self, program* prog)
|
||||||
case OP_FPOW: vm_fpow(self); break;
|
case OP_FPOW: vm_fpow(self); break;
|
||||||
|
|
||||||
case OP_ASSERT: vm_assert(self); break;
|
case OP_ASSERT: vm_assert(self); break;
|
||||||
|
|
||||||
|
case OP_SMUL: vm_smul(self); break;
|
||||||
|
case OP_CAT: vm_cat(self); break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
fprintf(stderr, "unknown opcode %s\n",
|
fprintf(stderr, "unknown opcode %s\n",
|
||||||
OpcodesStr[opcode]);
|
OpcodesStr[opcode]);
|
||||||
|
@ -482,3 +486,63 @@ void vm_assert(vm* self)
|
||||||
self->pc++;
|
self->pc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vm_smul(vm* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
size_t const SZ = 1024;
|
||||||
|
char val[SZ];
|
||||||
|
|
||||||
|
value* rhs = vm_pop_value(self);
|
||||||
|
value* lhs = vm_pop_value(self);
|
||||||
|
|
||||||
|
|
||||||
|
int n = lhs->val.integer;
|
||||||
|
size_t sz = 0;
|
||||||
|
|
||||||
|
for (int i=0; i<n; i++)
|
||||||
|
{
|
||||||
|
sz += snprintf(val + sz,
|
||||||
|
SZ - sz,
|
||||||
|
"%s",
|
||||||
|
rhs->val.string);
|
||||||
|
}
|
||||||
|
|
||||||
|
value* res = malloc(sizeof(val));
|
||||||
|
value_init_string(res, val, lhs->lineno);
|
||||||
|
|
||||||
|
vm_push_value(self, res);
|
||||||
|
|
||||||
|
value_free(lhs);
|
||||||
|
free(lhs);
|
||||||
|
|
||||||
|
value_free(rhs);
|
||||||
|
free(rhs);
|
||||||
|
|
||||||
|
self->pc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vm_cat(vm* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
size_t const SZ = 1024;
|
||||||
|
char val[SZ];
|
||||||
|
|
||||||
|
value* rhs = vm_pop_value(self);
|
||||||
|
value* lhs = vm_pop_value(self);
|
||||||
|
|
||||||
|
snprintf(val, SZ, "%s%s", lhs->val.string, rhs->val.string);
|
||||||
|
|
||||||
|
value* res = malloc(sizeof(value));
|
||||||
|
value_init_string(res, val, lhs->lineno);
|
||||||
|
vm_push_value(self, res);
|
||||||
|
|
||||||
|
value_free(lhs);
|
||||||
|
free(lhs);
|
||||||
|
|
||||||
|
value_free(rhs);
|
||||||
|
free(rhs);
|
||||||
|
|
||||||
|
self->pc++;
|
||||||
|
}
|
||||||
|
|
3
src/vm.h
3
src/vm.h
|
@ -50,6 +50,7 @@ void vm_fpow(vm* self);
|
||||||
void vm_eq(vm* self);
|
void vm_eq(vm* self);
|
||||||
void vm_assert(vm* self);
|
void vm_assert(vm* self);
|
||||||
|
|
||||||
|
void vm_smul(vm* self);
|
||||||
|
void vm_cat(vm* self);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
5 % 2.0
|
5 % 2.0
|
||||||
3.0 % 9
|
3.0 % 9
|
||||||
1.2 ^ 3
|
1.2 ^ 3
|
||||||
|
|
||||||
true + 2.0
|
true + 2.0
|
||||||
3.0 + false
|
3.0 + false
|
||||||
false - 2.0
|
false - 2.0
|
||||||
|
@ -21,7 +20,6 @@ true / 9
|
||||||
5 % false
|
5 % false
|
||||||
true % 9
|
true % 9
|
||||||
(false && false) ^ 3
|
(false && false) ^ 3
|
||||||
|
|
||||||
1.2 && 2.3
|
1.2 && 2.3
|
||||||
1.2 || 2.3
|
1.2 || 2.3
|
||||||
!12.0
|
!12.0
|
||||||
|
|
|
@ -6,25 +6,21 @@
|
||||||
1 / true
|
1 / true
|
||||||
1 % true
|
1 % true
|
||||||
1 ^ true
|
1 ^ true
|
||||||
|
|
||||||
true + 1
|
true + 1
|
||||||
true - 1
|
true - 1
|
||||||
true * 1
|
true * 1
|
||||||
true / 1
|
true / 1
|
||||||
true % 1
|
true % 1
|
||||||
true ^ 1
|
true ^ 1
|
||||||
|
|
||||||
true + false
|
true + false
|
||||||
true - false
|
true - false
|
||||||
true * false
|
true * false
|
||||||
true / false
|
true / false
|
||||||
true % false
|
true % false
|
||||||
true ^ false
|
true ^ false
|
||||||
|
|
||||||
1 && true
|
1 && true
|
||||||
2 || false
|
2 || false
|
||||||
!5
|
!5
|
||||||
|
|
||||||
true && 1
|
true && 1
|
||||||
false || -2
|
false || -2
|
||||||
!!5
|
!!5
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
+"a"
|
||||||
|
-"a"
|
||||||
|
5 + "a"
|
||||||
|
"z" + 2
|
||||||
|
3.1 + "mpm"
|
||||||
|
"true" + true
|
||||||
|
|
||||||
|
5 - "a"
|
||||||
|
"z" - 2
|
||||||
|
3.1 - "mpm"
|
||||||
|
"true" - true
|
||||||
|
|
||||||
|
3.1 * "mpm"
|
||||||
|
"true" * true
|
||||||
|
|
||||||
|
5 / "a"
|
||||||
|
"z" / 2
|
||||||
|
3.1 / "mpm"
|
||||||
|
"true" / true
|
||||||
|
|
||||||
|
5 % "a"
|
||||||
|
"z" % 2
|
||||||
|
3.1 % "mpm"
|
||||||
|
"true" % true
|
||||||
|
|
||||||
|
5 ^ "a"
|
||||||
|
"z" ^ 2
|
||||||
|
3.1 ^ "mpm"
|
||||||
|
"true" ^ true
|
||||||
|
|
||||||
|
"aze" && true
|
||||||
|
false && "eza"
|
||||||
|
|
||||||
|
"aze" || true
|
||||||
|
false || "eza"
|
||||||
|
|
||||||
|
!"eza"
|
||||||
|
|
||||||
|
"aze" && true
|
||||||
|
false && "eza"
|
||||||
|
|
|
@ -12,9 +12,9 @@ do
|
||||||
|
|
||||||
while read line;
|
while read line;
|
||||||
do
|
do
|
||||||
echo $line | wuz &> /dev/null
|
echo "$line" | wuz &> /dev/null
|
||||||
RET="$?"
|
RET="$?"
|
||||||
if [ $RET -ne 0 ] || [ "$line" == "" ]
|
if [ "$RET" != "0" ] || [ "$line" == "" ]
|
||||||
then
|
then
|
||||||
OK=$(($OK+1))
|
OK=$(($OK+1))
|
||||||
else
|
else
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
assert "salut" == "salut"
|
||||||
|
assert "salut" != "alut"
|
||||||
|
|
||||||
|
assert "hello world" == "hello " + "world"
|
||||||
|
|
||||||
|
assert "aaaa" == 4 * "a"
|
||||||
|
assert "aaaa" == "a" * 4
|
||||||
|
assert "abababab" == ("a" + "b") * 4
|
Loading…
Reference in New Issue