Skip to content

Commit 13663e4

Browse files
Added for loops, params, and handles
*Added python-esque for loops *Added pointer handles for custom objects/data types implemented in C++ *Added parameters for taking in variable-length arguments in procedures.
1 parent 419e661 commit 13663e4

File tree

14 files changed

+205
-56
lines changed

14 files changed

+205
-56
lines changed

src/Source.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ int main(int argc, char** argv) {
7575
return 1;
7676
}
7777
infile.seekg(0, std::ios::end);
78-
int buffer_length = infile.tellg();
78+
unsigned int buffer_length = infile.tellg();
7979
infile.seekg(0, std::ios::beg);
8080
char* buffer = new char[buffer_length + 1];
8181
infile.read(buffer, buffer_length);

src/io.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ namespace fastcode {
111111
//std::cout << '<' << ((structure*)val->ptr)->get_identifier()->get_identifier() << '>';
112112
xprint((runtime::structure*)val->ptr, 0);
113113
break;
114+
case VALUE_TYPE_HANDLE:
115+
std::cout << "<handle " << (long)val->ptr << ">";
116+
break;
114117
default:
115118
throw ERROR_INVALID_VALUE_TYPE;
116119
}

src/lexer.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@
3131
#define TOKEN_GROUP 16 + MAX_TOKEN_LIMIT
3232
#define TOKEN_END_GROUP 17 + MAX_TOKEN_LIMIT
3333

34-
#define END 18 + MAX_TOKEN_LIMIT
34+
#define TOKEN_IN_KW 18 + MAX_TOKEN_LIMIT
35+
36+
#define END 19 + MAX_TOKEN_LIMIT
3537

3638
namespace fastcode {
3739
namespace parsing {
@@ -143,6 +145,10 @@ namespace fastcode {
143145
return last_tok = new token(TOKEN_GROUP);
144146
case 303295209:
145147
return last_tok = new token(TOKEN_END_GROUP);
148+
case 193504908:
149+
return last_tok = new token(TOKEN_FOR);
150+
case 5863644:
151+
return last_tok = new token(TOKEN_IN_KW);
146152
case 193499145:
147153
while (last_char != '\n')
148154
read_char();
@@ -443,6 +449,17 @@ namespace fastcode {
443449
token* condition = tokenize_expression();
444450
return new conditional_token(TOKEN_WHILE, condition, tokenize_body(), nullptr);
445451
}
452+
case TOKEN_FOR: {
453+
delete last_tok;
454+
match_tok(read_token(), TOKEN_IDENTIFIER);
455+
identifier_token* id = (identifier_token*)last_tok;
456+
lexer_state->declare_id(id, GROUP_TYPE_VAR);
457+
match_tok(read_token(), TOKEN_IN_KW);
458+
delete last_tok;
459+
read_token();
460+
token* collection = tokenize_value();
461+
return new for_token(id, collection, tokenize_body());
462+
}
446463
case TOKEN_STRUCT_KW: {
447464
delete last_tok;
448465
match_tok(read_token(), TOKEN_IDENTIFIER);

src/lexer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ namespace fastcode {
144144
~lexer();
145145

146146
inline bool eos() {
147-
return last_tok == nullptr ? last_char == 0 : last_tok->type == 18 + MAX_TOKEN_LIMIT;
147+
return last_tok == nullptr ? last_char == 0 : last_tok->type == 19 + MAX_TOKEN_LIMIT;
148148
}
149149

150150
inline unsigned int get_pos() {

src/linq.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "builtins.h"
2+
#include "structure.h"
23
#include "collection.h"
34
#include "linq.h"
45

@@ -40,5 +41,42 @@ namespace fastcode {
4041
}
4142
return gc->new_apartment(new value(VALUE_TYPE_NUMERICAL, new long double((long double)instances)));
4243
}
44+
45+
runtime::reference_apartment* get_range(std::list<value*> arguments, runtime::garbage_collector* gc) {
46+
long double start = 0;
47+
long double step = 1;
48+
long double stop;
49+
if (arguments.size() == 1)
50+
stop = *arguments.front()->get_numerical();
51+
else if (arguments.size() == 2) {
52+
start = *arguments.front()->get_numerical();
53+
stop = *arguments.back()->get_numerical();
54+
}
55+
else if (arguments.size() == 3) {
56+
start = *arguments.front()->get_numerical();
57+
stop = *(*(++arguments.begin()))->get_numerical();
58+
step = *arguments.back()->get_numerical();
59+
}
60+
else
61+
throw ERROR_UNEXPECTED_ARGUMENT_SIZE;
62+
63+
unsigned long size = (stop - start) / step;
64+
65+
runtime::collection* range = new runtime::collection(size, gc);
66+
for (long double i = start; i < stop; i += step)
67+
range->set_value(i, new value(VALUE_TYPE_NUMERICAL, new long double(i)));
68+
return range->get_parent_ref();
69+
}
70+
71+
runtime::reference_apartment* get_handle(std::list<value*> arguments, runtime::garbage_collector* gc) {
72+
match_arg_len(arguments, 1);
73+
if (arguments.front()->type == VALUE_TYPE_STRUCT) {
74+
return gc->new_apartment(new value(VALUE_TYPE_HANDLE, ((runtime::structure*)arguments.front()->ptr)->get_parent_ref()));
75+
}
76+
else if (arguments.front()->type == VALUE_TYPE_COLLECTION) {
77+
return gc->new_apartment(new value(VALUE_TYPE_HANDLE, ((runtime::collection*)arguments.front()->ptr)->get_parent_ref()));
78+
}
79+
throw ERROR_INVALID_VALUE_TYPE;
80+
}
4381
}
4482
}

src/linq.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ namespace fastcode {
1313
runtime::reference_apartment* allocate_array(std::list<value*> arguments, runtime::garbage_collector* gc);
1414
runtime::reference_apartment* get_length(std::list<value*> arguments, runtime::garbage_collector* gc);
1515
runtime::reference_apartment* count_instances(std::list<value*> arguments, runtime::garbage_collector* gc);
16+
runtime::reference_apartment* get_range(std::list<value*> arguments, runtime::garbage_collector* gc);
17+
runtime::reference_apartment* get_handle(std::list<value*> arguments, runtime::garbage_collector* gc);
1618
}
1719
}
1820

src/objects.cpp

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@
66

77
namespace fastcode {
88
namespace parsing {
9+
10+
structure_prototype::structure_prototype(const char* identifier, const char* properties[], unsigned int property_count) : token(TOKEN_STRUCT_PROTO) {
11+
this->identifier = new identifier_token(identifier);
12+
this->property_count = property_count;
13+
this->property_order = new unsigned long[this->property_count];
14+
for (unsigned int i = 0; i < property_count; i++)
15+
this->property_order[i] = insecure_hash(properties[i]);
16+
}
17+
918
structure_prototype::structure_prototype(identifier_token* identifier, std::list<identifier_token*> identifiers) : token(TOKEN_STRUCT_PROTO) {
1019
this->identifier = identifier;
1120
this->property_count = identifiers.size();
@@ -35,9 +44,7 @@ namespace fastcode {
3544
namespace runtime {
3645
structure::structure(parsing::structure_prototype* prototype, garbage_collector* gc) : structure(prototype, gc->new_apartment(new value(VALUE_TYPE_STRUCT, this))) {
3746
for (size_t i = 0; i < prototype->property_count; i++)
38-
{
3947
this->properties[i] = gc->new_apartment(new value(VALUE_TYPE_NULL, nullptr));
40-
}
4148
}
4249

4350
structure::structure(parsing::structure_prototype* prototype, reference_apartment* parent_reference) {
@@ -47,10 +54,6 @@ namespace fastcode {
4754
}
4855

4956
structure::~structure() {
50-
for (size_t i = 0; i < prototype->property_count; i++)
51-
{
52-
//this->properties[i]->remove_reference();
53-
}
5457
delete[] this->properties;
5558
}
5659

@@ -106,31 +109,21 @@ namespace fastcode {
106109
this->inner_collection = new reference_apartment * [size];
107110
}
108111

109-
collection::~collection() {/*
110-
for (size_t i = 0; i < size; i++)
111-
{
112-
if(!this->inner_collection[i]->can_delete())
113-
this->inner_collection[i]->remove_reference();
114-
}*/
112+
collection::~collection() {
115113
delete this->inner_collection;
116114
}
117115

118116
collection* collection::clone(reference_apartment* new_parent_apptr) {
119117
collection* copy = new collection(this->size, new_parent_apptr);
120118
for (unsigned long i = 0; i < size; i++)
121-
{
122119
copy->inner_collection[i] = this->inner_collection[i];
123-
//this->inner_collection[i]->add_reference();
124-
}
125120
return copy;
126121
}
127122

128123
int collection::hash() {
129124
int hash = 66; //magic number for collection hahses
130125
for (size_t i = 0; i < this->size; i++)
131-
{
132126
hash = combine_hash(hash, this->inner_collection[i]->value->hash());
133-
}
134127
return hash;
135128
}
136129

@@ -167,6 +160,8 @@ namespace fastcode {
167160
case VALUE_TYPE_STRUCT:
168161
delete (runtime::structure*)this->ptr;
169162
break;
163+
case VALUE_TYPE_HANDLE:
164+
break;
170165
default:
171166
throw ERROR_INVALID_VALUE_TYPE;
172167
}
@@ -183,6 +178,8 @@ namespace fastcode {
183178
return ((runtime::collection*)this->ptr)->hash();
184179
case VALUE_TYPE_STRUCT:
185180
return ((runtime::structure*)this->ptr)->hash();
181+
case VALUE_TYPE_HANDLE:
182+
return int(this->ptr);
186183
default:
187184
throw ERROR_INVALID_VALUE_TYPE;
188185
}

src/runtime.cpp

Lines changed: 56 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ namespace fastcode {
4242
import_func("input", builtins::get_input);
4343
import_func("array", builtins::allocate_array);
4444
import_func("len", builtins::get_length);
45+
import_func("range", builtins::get_range);
46+
import_func("handle", builtins::get_handle);
4547
import_func("read@file", builtins::file_read_text);
4648
import_func("write@file", builtins::file_write_text);
4749
import_func("count@linq", builtins::count_instances);
@@ -148,13 +150,6 @@ namespace fastcode {
148150
}
149151
}
150152

151-
void interpreter::import_func(const char* identifier, builtins::built_in_function function) {
152-
unsigned long id_hash = insecure_hash(identifier);
153-
if (built_in_functions.count(id_hash))
154-
throw ERROR_FUNCTION_PROTO_ALREADY_DEFINED;
155-
built_in_functions[id_hash] = function;
156-
}
157-
158153
void interpreter::set_ref(parsing::variable_access_token* access, reference_apartment* reference) {
159154
if (access->modifiers.size() == 1) {
160155
if (static_var_manager->has_var(access->get_identifier()))
@@ -401,21 +396,37 @@ namespace fastcode {
401396
parsing::function_call_token* func_call = (parsing::function_call_token*)eval_tok;
402397
if (function_definitions.count(func_call->identifier->id_hash)) {
403398
parsing::function_prototype* to_execute = function_definitions[func_call->identifier->id_hash];
404-
if (func_call->arguments.size() != to_execute->argument_identifiers.size())
405-
throw ERROR_UNEXPECTED_ARGUMENT_SIZE;
406399
call_frame* new_frame = new call_frame(to_execute, &garbage_collector);
407-
unsigned int i = 0;
408-
auto arg_id_it = to_execute->argument_identifiers.begin();
409-
for (auto arg_val_it = func_call->arguments.begin(); arg_val_it != func_call->arguments.end(); ++arg_val_it) {
410-
value_eval* arg_eval = evaluate(*arg_val_it, true);
411-
if (arg_eval->type == VALUE_EVAL_TYPE_REF)
412-
new_frame->manager->declare_var(*arg_id_it, arg_eval->get_reference());
413-
else {
414-
arg_eval->keep();
415-
new_frame->manager->declare_var(*arg_id_it, arg_eval->get_value());
400+
if (to_execute->is_params()) {
401+
unsigned int i = 0;
402+
collection* param_args = new collection(func_call->arguments.size(), &garbage_collector);
403+
for (auto arg_val_it = func_call->arguments.begin(); arg_val_it != func_call->arguments.end(); ++arg_val_it) {
404+
value_eval* arg_eval = evaluate(*arg_val_it, true);
405+
if (arg_eval->type == VALUE_EVAL_TYPE_REF)
406+
param_args->set_reference(i++, arg_eval->get_reference());
407+
else {
408+
arg_eval->keep();
409+
param_args->set_value(i++, arg_eval->get_value());
410+
}
411+
delete arg_eval;
412+
}
413+
new_frame->manager->declare_var(470537897, param_args->get_parent_ref());
414+
}
415+
else {
416+
if (func_call->arguments.size() != to_execute->argument_identifiers.size())
417+
throw ERROR_UNEXPECTED_ARGUMENT_SIZE;
418+
auto arg_id_it = to_execute->argument_identifiers.begin();
419+
for (auto arg_val_it = func_call->arguments.begin(); arg_val_it != func_call->arguments.end(); ++arg_val_it) {
420+
value_eval* arg_eval = evaluate(*arg_val_it, true);
421+
if (arg_eval->type == VALUE_EVAL_TYPE_REF)
422+
new_frame->manager->declare_var(*arg_id_it, arg_eval->get_reference());
423+
else {
424+
arg_eval->keep();
425+
new_frame->manager->declare_var(*arg_id_it, arg_eval->get_value());
426+
}
427+
delete arg_eval;
428+
arg_id_it++;
416429
}
417-
delete arg_eval;
418-
arg_id_it++;
419430
}
420431
call_stack.push(new_frame);
421432
value_eval* ret_val = execute_block(to_execute->tokens);
@@ -508,6 +519,31 @@ namespace fastcode {
508519
}
509520
break;
510521
}
522+
case TOKEN_FOR: {
523+
parsing::for_token* for_tok = (parsing::for_token*)*it;
524+
value_eval* to_iterate_eval = evaluate(for_tok->collection, true);
525+
if (to_iterate_eval->get_value()->type != VALUE_TYPE_COLLECTION)
526+
throw ERROR_MUST_HAVE_COLLECTION_TYPE;
527+
collection* to_iterate = (collection*)to_iterate_eval->get_value()->ptr;
528+
delete to_iterate_eval;
529+
530+
call_stack.top()->manager->declare_var(for_tok->identifier, new value(VALUE_TYPE_NULL, nullptr));
531+
532+
for (size_t i = 0; i < to_iterate->size; i++)
533+
{
534+
call_stack.top()->manager->set_var_reference(for_tok->identifier, to_iterate->get_reference(i));
535+
value_eval* eval = execute_block(for_tok->instructions);
536+
if (eval != nullptr) {
537+
return eval;
538+
}
539+
else if (break_mode) {
540+
break_mode = false;
541+
return nullptr;
542+
}
543+
}
544+
call_stack.top()->manager->remove_var(for_tok->identifier);
545+
break;
546+
}
511547
case TOKEN_UNIARY_OP:
512548
case TOKEN_FUNCTION_CALL:
513549
case TOKEN_SET:

src/runtime.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,18 @@ namespace fastcode {
127127

128128
void include(const char* file_path);
129129

130-
void import_func(const char* identifier, builtins::built_in_function function);
130+
inline void import_func(const char* identifier, builtins::built_in_function function) {
131+
unsigned long id_hash = insecure_hash(identifier);
132+
if (built_in_functions.count(id_hash))
133+
throw ERROR_FUNCTION_PROTO_ALREADY_DEFINED;
134+
built_in_functions[id_hash] = function;
135+
}
136+
137+
inline void import_struct(parsing::structure_prototype* struct_proto) {
138+
if (struct_definitions.count(struct_proto->identifier->id_hash))
139+
throw ERROR_STRUCT_PROTO_ALREADY_DEFINED;
140+
struct_definitions[struct_proto->identifier->id_hash] = struct_proto;
141+
}
131142

132143
inline void new_constant(const char* identifier, value* val) {
133144
this->lexer_state.constants[insecure_hash(identifier)] = new parsing::value_token(val);

src/structure.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ namespace fastcode {
2020

2121
unsigned int property_count;
2222

23+
structure_prototype(const char* identifier, const char* properties[], unsigned int property_couunt);
2324
structure_prototype(identifier_token* identifier, std::list<identifier_token*> properties);
2425
~structure_prototype();
2526

src/tokens.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ namespace fastcode {
7272
case TOKEN_WHILE:
7373
delete (conditional_token*)token;
7474
break;
75+
case TOKEN_FOR:
76+
delete (for_token*)token;
77+
break;
7578
case TOKEN_BREAK:
7679
delete token;
7780
break;
@@ -225,6 +228,19 @@ namespace fastcode {
225228
throw ERROR_UNRECOGNIZED_TOKEN;
226229
}
227230

231+
for_token::for_token(identifier_token* identifier, token* collection, std::list<token*> instructions) : token(TOKEN_FOR){
232+
this->collection = collection;
233+
this->identifier = identifier;
234+
this->instructions = instructions;
235+
}
236+
237+
for_token::~for_token() {
238+
destroy_value_tok(this->collection);
239+
delete this->identifier;
240+
for (auto i = instructions.begin(); i != instructions.end(); ++i)
241+
destroy_top_lvl_tok(*i);
242+
}
243+
228244
create_array_token::create_array_token(std::list<token*> values) : token(TOKEN_CREATE_ARRAY) {
229245
for (auto i = values.begin(); i != values.end(); ++i)
230246
if (!is_value_tok(*i))

0 commit comments

Comments
 (0)