Skip to content

Commit 1ebd2c7

Browse files
committed
Add checking of number of parameters of PROC/EXEC to the cross-compiler.
1 parent 220c4f5 commit 1ebd2c7

5 files changed

Lines changed: 116 additions & 22 deletions

File tree

src/basic.syn

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ EXTERN {
9595

9696
#@if EXTENDED
9797
E_DATA_FILE
98+
E_COUNT_PARAM
99+
E_PROC_CHECK
98100
#@endif
99101

100102
#@if FASTBASIC_FP
@@ -635,12 +637,23 @@ OPT_EXEC_PARAM:
635637
pass
636638

637639
EXEC_PARAM_MORE:
640+
#@if EXTENDED
641+
# In the cross-compiler, we count parameters to detect program errors
642+
E_COUNT_PARAM
643+
#@endif
638644
C_EXPR EXEC_PARAM_MORE
639645
pass
640646

641647
# Optional variable in PROC
642648
OPT_PROC_VAR:
649+
#@if EXTENDED
650+
# In the cross-compiler, we count parameters to detect program errors
651+
E_COUNT_PARAM
652+
#@endif
643653
VAR_WORD_SAVE OPT_PROC_VAR emit { TOK_POP, TOK_VAR_STORE } E_POP_VAR
654+
#@if EXTENDED
655+
E_PROC_CHECK
656+
#@endif
644657
pass
645658

646659
# Parse a line

src/compiler/parser.cc

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,6 @@ bool SMB_E_NUMBER_FP(parse &s)
575575

576576
#endif
577577

578-
static std::string last_label_name;
579578
bool SMB_E_LABEL_DEF(parse &s)
580579
{
581580
s.debug("E_LABEL_DEF");
@@ -584,10 +583,11 @@ bool SMB_E_LABEL_DEF(parse &s)
584583
if( !s.get_ident(name) )
585584
return false;
586585
if( v.find(name) == v.end() )
587-
v[name] = VT_UNDEF;
588-
if( v[name] != VT_UNDEF )
586+
v[name] = labelType();
587+
if( v[name].is_defined() )
589588
return false;
590-
last_label_name = name;
589+
s.last_label = name;
590+
s.current_params = 0;
591591
s.add_text(name);
592592
s.emit_label("fb_lbl_" + name);
593593
return true;
@@ -597,61 +597,81 @@ bool SMB_E_LABEL(parse &s)
597597
{
598598
s.debug("E_LABEL");
599599
// Get type
600-
enum VarType type = get_vartype(s.remove_last().get_str());
601-
auto &v = s.labels;
600+
auto ltype = labelType(s.remove_last().get_str());
601+
// Get identifier
602602
std::string name;
603603
if( !s.get_ident(name) )
604604
return false;
605-
if( v.find(name) == v.end() )
605+
auto it = s.labels.find(name);
606+
if( it == s.labels.end() )
606607
return false;
607608
// Check type
608-
if( v[name] != type )
609+
if( it->second != ltype )
609610
return false;
610611
s.add_text(name);
611612
s.emit_word("fb_lbl_" + name);
612613
return true;
613614
}
614615

616+
bool SMB_E_COUNT_PARAM(parse &s)
617+
{
618+
s.debug("E_COUNT_PARAM");
619+
s.current_params ++;
620+
return false;
621+
}
622+
615623
// Called in EXEC, creates a label if not exists, if already exists checks
616624
// that it is a PROC.
617625
bool SMB_E_LABEL_CREATE(parse &s)
618626
{
619627
s.debug("E_LABEL_CREATE");
620-
// Get type
621-
auto &v = s.labels;
622628
std::string name;
623629
if( !s.get_ident(name) )
624630
return false;
625-
// Create if not exists
626-
if( v.find(name) == v.end() )
627-
v[name] = VT_UNDEF;
631+
// Get type, create if not exists
632+
auto &v = s.labels[name];
628633
// Check type
629-
if( v[name] != VT_UNDEF )
634+
if( !v.is_proc() )
630635
return false;
631636
// Store variable name
632637
s.add_text(name);
633638
s.last_label = name;
639+
s.current_params = 0;
634640
return true;
635641
}
636642

637643
bool SMB_E_DO_EXEC(parse &s)
638644
{
645+
int pnum = s.current_params;
639646
s.debug("E_DO_EXEC");
647+
auto &l = s.labels[s.last_label];
648+
if( !l.add_proc_params(pnum) )
649+
throw parse_error("invalid number of parameters in EXEC, expected " +
650+
std::to_string(l.num_params()) + ", got "
651+
+ std::to_string(pnum) , s.pos);
640652
s.emit_word("fb_lbl_" + s.last_label);
641653
return true;
642654
}
643655

656+
bool SMB_E_PROC_CHECK(parse &s)
657+
{
658+
int pnum = s.current_params - 1;
659+
s.debug("E_PROC_CHECK");
660+
auto &l = s.labels[s.last_label];
661+
if( !l.add_proc_params(pnum) )
662+
throw parse_error("invalid number of parameters in PROC, expected " +
663+
std::to_string(l.num_params()) + ", got "
664+
+ std::to_string(pnum) , s.pos);
665+
l.define();
666+
return true;
667+
}
668+
644669
bool SMB_E_LABEL_SET_TYPE(parse &s)
645670
{
646671
s.debug("E_LABEL_SET_TYPE");
647-
648672
s.skipws();
649673
// Get type
650-
enum VarType type = get_vartype(s.remove_last().get_str());
651-
auto &v = s.labels;
652-
if( do_debug )
653-
std::cout << "\tset label '" << last_label_name << "' to " << int(type) << "\n";
654-
v[last_label_name] = (v[last_label_name] & ~0xFF) + type;
674+
s.labels[s.last_label] = labelType(s.remove_last().get_str());
655675
return true;
656676
}
657677

src/compiler/parser.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "codew.h"
2424
#include "looptype.h"
25+
#include "vartype.h"
2526

2627
#include <algorithm>
2728
#include <map>
@@ -68,12 +69,13 @@ class parse {
6869
std::map<std::string, std::vector<codew>> procs;
6970
std::vector<std::string> proc_stack;
7071
std::map<std::string, int> vars;
71-
std::map<std::string, int> labels;
72+
std::map<std::string, labelType> labels;
7273
std::vector<jump> jumps;
7374
int label_num;
7475
bool finalized;
7576
std::vector<codew> *code;
76-
std::string last_label;
77+
std::string last_label; // Last label to be referenced in an EXEC
78+
int current_params; // Number of parameters in PROC/EXEC being parsed
7779
// Used to store an un-abbreviated line
7880
struct expand_line {
7981
std::string text;

src/compiler/vartype.cc

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
// vartype.cc: Defines types of variables
2020

2121
#include "vartype.h"
22+
#include <stdexcept>
2223

2324
VarType get_vartype(std::string t)
2425
{
@@ -82,3 +83,42 @@ bool var_type_is_array(enum VarType t)
8283
return false;
8384
}
8485

86+
labelType::labelType(): type(0) {}
87+
88+
labelType::labelType(std::string str)
89+
{
90+
if( str == "VT_ARRAY_WORD" )
91+
type = 128;
92+
else if( str == "VT_ARRAY_BYTE" )
93+
type = 129;
94+
else
95+
throw std::runtime_error("invalid label type " + str);
96+
}
97+
98+
bool labelType::is_defined()
99+
{
100+
return type >= 64;
101+
}
102+
103+
bool labelType::is_proc()
104+
{
105+
return type < 128;
106+
}
107+
108+
bool labelType::add_proc_params(int params)
109+
{
110+
if( !type )
111+
type = params + 1;
112+
113+
return num_params() == params;
114+
}
115+
116+
int labelType::num_params()
117+
{
118+
return (type & 63) - 1;
119+
}
120+
121+
void labelType::define()
122+
{
123+
type |= 64;
124+
}

src/compiler/vartype.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#pragma once
2222
#include <string>
2323

24+
// Variable types
2425
enum VarType {
2526
VT_UNDEF = 0,
2627
VT_WORD,
@@ -36,3 +37,21 @@ VarType get_vartype(std::string t);
3637
std::string get_vt_name(enum VarType t);
3738
bool var_type_is_array(enum VarType t);
3839

40+
// Label types
41+
class labelType {
42+
public:
43+
// Create from string in parser file
44+
labelType(std::string t);
45+
labelType();
46+
bool is_defined();
47+
bool is_proc();
48+
bool add_proc_params(int params);
49+
int num_params();
50+
void define();
51+
bool operator !=(const labelType &l) const { return type != l.type; }
52+
private:
53+
int type;
54+
};
55+
56+
57+

0 commit comments

Comments
 (0)