Skip to content

Commit ba2cb88

Browse files
committed
WIP
1 parent 2a4698f commit ba2cb88

4 files changed

Lines changed: 139 additions & 42 deletions

File tree

generator.cpp

Lines changed: 84 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ const GeneratorFuncSpec Generator::m_funcspecs[] =
115115
{ KeywordCSNG, &Generator::GenerateFuncCsng },
116116
{ KeywordASC, &Generator::GenerateFuncAsc },
117117
{ KeywordCHR, &Generator::GenerateFuncChr },
118+
{ KeywordSTRING, &Generator::GenerateFuncString },
118119
{ KeywordIIF, &Generator::GenerateFuncIif },
119120
};
120121

@@ -2407,17 +2408,11 @@ void Generator::GenerateLogicOperArguments(const ExpressionModel& expr, const Ex
24072408
}
24082409
else if (nodeleft.vtype == ValueTypeString)
24092410
{
2410-
if (noderight.vtype == ValueTypeInteger || noderight.vtype == ValueTypeSingle)
2411-
{
2412-
assert(false); // Compare String <=> Integer/Single should be covered in validation
2413-
}
2414-
else
2415-
{
2416-
assert(noderight.vtype == ValueTypeString);
2417-
AddRuntimeCall(RuntimeSTCM);
2418-
AddComment("TODO compare String to String");
2419-
//TODO
2420-
}
2411+
assert(noderight.vtype == ValueTypeString); // Compare String <=> Integer/Single should be covered in validation
2412+
2413+
AddRuntimeCall(RuntimeSTCM);
2414+
AddComment("TODO compare String to String");
2415+
//TODO
24212416
}
24222417
}
24232418

@@ -2474,8 +2469,16 @@ void Generator::GenerateOperNotEqual(const ExpressionModel& expr, const Expressi
24742469
GenerateExpression(expr, noderight); // result in R0
24752470
AddLine("\tTSTB\t(R0)");
24762471
}
2477-
//TODO Special case: String <> 1-char String
2478-
2472+
// Special case: String <> 1-char String
2473+
else if (nodeleft.vtype == ValueTypeString && noderight.vtype == ValueTypeString &&
2474+
noderight.constval && noderight.GetConstStringValue().size() == 1)
2475+
{
2476+
GenerateExpression(expr, nodeleft); // result in R0
2477+
string svalue = noderight.GetConstStringValue();
2478+
//NOTE: Character conversion depends on encoding
2479+
uint16_t value = (1 << 8) | svalue[0];
2480+
AddLine("\tCMP\t(R0), #" + to_string_octal(value));
2481+
}
24792482
// all other cases
24802483
else
24812484
{
@@ -3245,6 +3248,74 @@ void Generator::GenerateFuncChr(const ExpressionModel& expr, const ExpressionNod
32453248

32463249
//TODO: Allocate dynamic 1-char string
32473250
//TODO: String length = 1, MOVB R0 to first char of the string
3251+
AddComment("TODO CHR$");
3252+
}
3253+
3254+
// X¤=STRING¤(<АРГУМЕНТ1>,<АРГУМЕНТ2>)
3255+
// result is String
3256+
void Generator::GenerateFuncString(const ExpressionModel& expr, const ExpressionNode& node)
3257+
{
3258+
assert(node.args.size() == 2);
3259+
3260+
const ExpressionModel& expr1 = node.args[0];
3261+
assert(expr1.GetExpressionValueType() != ValueTypeString);
3262+
3263+
const ExpressionModel& expr2 = node.args[1];
3264+
3265+
if (expr1.IsConstExpression())
3266+
{
3267+
int ivalue = (int)std::floor(expr1.GetConstExpressionDValue());
3268+
assert(ivalue >= 0 && ivalue <= 255);
3269+
if (ivalue == 0)
3270+
{
3271+
Warning(node.token, "STRING$(0, ...) reduced to empty string; consider to replace this expression with \"\".");
3272+
AddLine("\tMOV\tST0, R0");
3273+
return;
3274+
}
3275+
3276+
GenerateExpression(expr2);
3277+
if (expr2.GetExpressionValueType() == ValueTypeSingle)
3278+
AddRuntimeCall(RuntimeFTOI, "to Integer"); // result in R0
3279+
//TODO: If the string is empty, result is empty string (already in R0)
3280+
3281+
//TODO: Allocate string with the given length
3282+
//TODO: Fill the string
3283+
AddComment("TODO STRING$");
3284+
return;
3285+
}
3286+
3287+
if (expr2.IsConstExpression())
3288+
{
3289+
ValueType expr2vtype = expr2.GetExpressionValueType();
3290+
if (expr2vtype == ValueTypeString && expr2.GetConstExpressionSValue() == "")
3291+
{
3292+
Warning(node.token, "STRING$(..., \"\") reduced to empty string; consider to replace this expression with \"\".");
3293+
AddLine("\tMOV\tST0, R0");
3294+
return;
3295+
}
3296+
3297+
GenerateExpression(expr1);
3298+
if (expr1.GetExpressionValueType() == ValueTypeSingle)
3299+
AddRuntimeCall(RuntimeFTOI, "to Integer"); // result in R0
3300+
3301+
//TODO: Allocate string with the given length
3302+
//TODO: Fill the string
3303+
AddComment("TODO STRING$");
3304+
return;
3305+
}
3306+
3307+
GenerateExpression(expr1);
3308+
if (expr1.GetExpressionValueType() == ValueTypeSingle)
3309+
AddRuntimeCall(RuntimeFTOI, "to Integer"); // result in R0
3310+
3311+
GenerateExpression(expr2);
3312+
if (expr2.GetExpressionValueType() == ValueTypeSingle)
3313+
AddRuntimeCall(RuntimeFTOI, "to Integer"); // result in R0
3314+
//TODO: If the string is empty, result is empty string (already in R0)
3315+
3316+
//TODO: Allocate string with the given length
3317+
//TODO: Fill the string
3318+
AddComment("TODO STRING$");
32483319
}
32493320

32503321
// X=IIF(<ЛОГИЧЕСКОЕ ВЫРАЖЕНИЕ>,<АРИФМЕТИЧЕСКОЕ ВЫРАЖЕНИЕ>,<АРИФМЕТИЧЕСКОЕ ВЫРАЖЕНИЕ>)

main.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,7 @@ class Generator
783783
void GenerateFuncCsng(const ExpressionModel& expr, const ExpressionNode& node);
784784
void GenerateFuncAsc(const ExpressionModel& expr, const ExpressionNode& node);
785785
void GenerateFuncChr(const ExpressionModel& expr, const ExpressionNode& node);
786+
void GenerateFuncString(const ExpressionModel& expr, const ExpressionNode& node);
786787
void GenerateFuncIif(const ExpressionModel& expr, const ExpressionNode& node);
787788
};
788789

runtime-UKNC.tmac

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -191,17 +191,36 @@ STOP$3: .ASCII <10.>/ src line /
191191
;## Need WRST
192192
;## Need WRINT
193193
; Показ сообщения об ошибке времени выполнения.
194-
; На входе: R0 = номер ошибки, R5 = адрес откуда вызвана процедура.
194+
; На входе: R5 = адрес откуда вызвана процедура, в которой произошла ошибка.
195+
; Использование:
196+
; CALL ERRR
197+
; .WORD 1234. ; Номер ошибки
195198
ERRR:
196-
MOV R0, -(SP)
199+
MOV R5, -(SP) ; сохраняем адрес
197200
MOV #ERRO$, R0
198201
CALL WRST
199-
MOV (SP)+, R0 ; номер ошибки
202+
MOV 2(SP), R0 ; откуда вызвана ERRR
203+
MOV (R0), R0 ; номер ошибки
200204
CALL WRINT
201-
;TODO: Вывести " AT " и адрес R5 в восьмеричном виде
205+
MOV (SP)+, R5 ; адрес откуда вызвали
206+
; Формируем 8-ричное представление числа R5 в ERRR$
207+
MOV #6, R2 ; счетчик цифр
208+
MOV #ERRR$+5+6, R1 ; указатель на адрес за концом буфера
209+
1$: MOV R5, R0 ; копия для выделения младших 3 бит
210+
BIC #177770, R0 ; оставить только 0..7
211+
ADD #'0, R0 ; преобразовать в ASCII-символ
212+
MOVB R0, -(R1) ; записать символ в буфер
213+
ASR R5 ; сдвиг числа вправо на 3 бита
214+
ASR R5
215+
ASR R5
216+
SOB R2, 1$ ; повторить
217+
; Вывести " AT " и адрес R5 в восьмеричном виде
218+
MOV #ERRR$, R0
219+
CALL WRST
202220
BR . ; зацикливаемся здесь
203221
;
204222
ERRO$: .ASCII <6>/ERROR /
223+
ERRR$: .ASCII <10.>/ AT 000000/
205224
.EVEN
206225

207226
;#####################################################################
@@ -299,8 +318,8 @@ IMUL:
299318
RETURN ; возврат
300319
;
301320
IMULOV: MOV (SP), R5 ; откуда вызвали
302-
MOV #1706., R0 ; Ошибка: переполнение
303-
JMP ERRR
321+
CALL ERRR
322+
.WORD 1706. ; Ошибка: переполнение
304323

305324
;#####################################################################
306325
;## IDIV
@@ -320,11 +339,11 @@ IDIV:
320339
RETURN
321340
;
322341
IDIV0: MOV (SP), R5 ; откуда вызвали
323-
MOV #1811., R0 ; Ошибка: деление на ноль
324-
JMP ERRR
342+
CALL ERRR
343+
.WORD 1811. ; Ошибка: деление на ноль
325344
IDIVOV: MOV (SP), R5 ; откуда вызвали
326-
MOV #1806., R0 ; Ошибка: переполнение
327-
JMP ERRR
345+
CALL ERRR
346+
.WORD 1806. ; Ошибка: переполнение
328347

329348
;#####################################################################
330349
;## ITOF
@@ -417,8 +436,8 @@ FTOI:
417436
BCS 6$ ; если знак отрицательный, -32768 допустим
418437
;
419438
FTOIOV: MOV (SP), R5 ; откуда вызвали
420-
MOV #2006., R0 ; Ошибка: недопустимое значение или переполнение
421-
JMP ERRR
439+
CALL ERRR
440+
.WORD 2006. ; Ошибка: недопустимое значение или переполнение
422441

423442
;#####################################################################
424443
;## FFIX
@@ -1263,8 +1282,8 @@ FSQR$E: MOV R0, (SP) ;
12631282
FSQR$X: JMP @#000000 ; возврат, адрес подставляется в начале
12641283
;
12651284
FSQR$K: MOV FSQR$X+2, R5 ; откуда вызвали
1266-
MOV #3605., R0 ; Ошибка: корень из отрицательного числа
1267-
JMP ERRR
1285+
CALL ERRR
1286+
.WORD 3605. ; Ошибка: корень из отрицательного числа
12681287

12691288
;#####################################################################
12701289
;## FCOS
@@ -1410,8 +1429,8 @@ FTAN:
14101429
RETURN ; возврат
14111430
;
14121431
FTAN$0: MOV (SP), R5 ; откуда вызвали
1413-
MOV #4111., R0 ; Ошибка: деление на ноль
1414-
JMP ERRR
1432+
CALL ERRR
1433+
.WORD 4111. ; Ошибка: деление на ноль
14151434

14161435
;#####################################################################
14171436
;## FATN
@@ -1585,11 +1604,11 @@ REAI:
15851604
JMP REST ; делаем RESTORE на этот дескриптор
15861605
;
15871606
REAI$O: MOV (SP), R5 ; откуда вызвали
1588-
MOV #4604., R0 ; Ошибка: чтение за концом данных
1589-
JMP ERRR
1607+
CALL ERRR
1608+
.WORD 4604. ; Ошибка: чтение за концом данных
15901609
REAI$T: MOV (SP), R5 ; откуда вызвали
1591-
MOV #4613., R0 ; Ошибка: несоответствие типов данных
1592-
JMP ERRR
1610+
CALL ERRR
1611+
.WORD 4613. ; Ошибка: несоответствие типов данных
15931612

15941613
;#####################################################################
15951614
;## REAF
@@ -1629,11 +1648,11 @@ REAF:
16291648
JMP REST ; делаем RESTORE на этот дескриптор
16301649
;
16311650
REAF$O: MOV (SP), R5 ; откуда вызвали
1632-
MOV #4704., R0 ; Ошибка: чтение за концом данных
1633-
JMP ERRR
1651+
CALL ERRR
1652+
.WORD 4704. ; Ошибка: чтение за концом данных
16341653
REAF$T: MOV (SP), R5 ; откуда вызвали
1635-
MOV #4713., R0 ; Ошибка: несоответствие типов данных
1636-
JMP ERRR
1654+
CALL ERRR
1655+
.WORD 4713. ; Ошибка: несоответствие типов данных
16371656

16381657
;#####################################################################
16391658
;## REAS
@@ -1663,11 +1682,11 @@ REAS:
16631682
8$: JMP REST ; делаем RESTORE на этот дескриптор
16641683
;
16651684
REAS$O: MOV (SP), R5 ; откуда вызвали
1666-
MOV #4804., R0 ; Ошибка: чтение за концом данных
1667-
JMP ERRR
1685+
CALL ERRR
1686+
.WORD 4804. ; Ошибка: чтение за концом данных
16681687
REAS$T: MOV (SP), R5 ; откуда вызвали
1669-
MOV #4813., R0 ; Ошибка: несоответствие типов данных
1670-
JMP ERRR
1688+
CALL ERRR
1689+
.WORD 4813. ; Ошибка: несоответствие типов данных
16711690

16721691
;#####################################################################
16731692
;## INKEY

validator.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1869,7 +1869,11 @@ void Validator::ValidateFuncSqr(ExpressionModel& expr, ExpressionNode& node)
18691869

18701870
if (node.constval)
18711871
{
1872-
node.token.dvalue = sqrt(expr1.GetConstExpressionDValue());
1872+
double dvalue = expr1.GetConstExpressionDValue();
1873+
if (dvalue < 0.0)
1874+
EXPR_ERROR("Square root with negative argument.");
1875+
1876+
node.token.dvalue = sqrt(dvalue);
18731877
//TODO: if (node.token.IsDValueInteger())
18741878
}
18751879
}
@@ -2138,6 +2142,8 @@ void Validator::ValidateFuncMid(ExpressionModel& expr, ExpressionNode& node)
21382142
}
21392143
}
21402144

2145+
// X¤=STRING¤(<АРГУМЕНТ1>,<АРГУМЕНТ2>)
2146+
// result is String
21412147
void Validator::ValidateFuncString(ExpressionModel& expr, ExpressionNode& node)
21422148
{
21432149
if (node.args.size() != 2)

0 commit comments

Comments
 (0)