Skip to content

Commit

Permalink
Поправлена генерация в JavaScript арифметики с контролем переполнения
Browse files Browse the repository at this point in the history
  • Loading branch information
ComdivByZero authored and ComdivByZero committed Jan 14, 2021
1 parent f9fb95f commit 5196e44
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 28 deletions.
70 changes: 59 additions & 11 deletions singularity/implementation.js/o7.js
Expand Up @@ -475,7 +475,7 @@ var o7;

o7.mul = function(a, b) {
var r;
r = a * b | 0;
r = a * b;
if (-0x80000000 < r && r < 0x80000000) {
return r;
} else {
Expand All @@ -489,7 +489,7 @@ var o7;
mask = a >> 31;
return mask ^ ((mask ^ a) / b);
} else {
throw new RangeError("divider can't be < 1");
throw new RangeError("Integer divider can't be < 1");
}
};

Expand All @@ -499,10 +499,58 @@ var o7;
mask = a >> 31;
return (b & mask) + (mask ^ ((mask ^ a) % b));
} else {
throw new RangeError("divider can't be < 1");
throw new RangeError("Integer divider can't be < 1");
}
};

function fadd(a, b) {
var s;
s = a + b;
if (isFinite(s)) {
return s;
} else {
/* TODO */
throw new RangeError("Fraction out of range in " + a + " + " + b + " = " + s);
}
}
o7.fadd = fadd;

function fsub(a, b) {
var s;
s = a - b;
if (isFinite(s)) {
return s;
} else {
/* TODO */
throw new RangeError("Fraction out of range in " + a + " - " + b + " = " + s);
}
}
o7.fsub = fsub;

function fmul(a, b) {
var s;
s = a * b;
if (isFinite(s)) {
return s;
} else {
/* TODO */
throw new RangeError("Fraction out of range in " + a + " * " + b + " = " + s);
}
}
o7.fmul = fmul;

function fdiv(a, b) {
var s;
s = a / b;
if (isFinite(s)) {
return s;
} else {
/* TODO */
throw new RangeError("Fraction out of range in " + a + " / " + b + " = " + s);
}
}
o7.fdiv = fdiv;

o7.set = function(low, high) {
if (high > 31) {
throw new RangeError("high limit = " + high + " > 31");
Expand Down Expand Up @@ -587,18 +635,18 @@ var o7;
for (i = 0; i < len; i += 1) {
d[i] = s[i];
}
assert(i == len);
assert(d[len - 1] == 0);
};

o7.copy = function(d, s) {
var i, len;
d = getjsa(d);
s = getjsa(s);
len = d.length;
for (i = 0; i < len; i += 1) {
d[i] = s[i];
}
var i, len;
d = getjsa(d);
s = getjsa(s);
len = d.length;
for (i = 0; i < len; i += 1) {
/* TODO вложенные массивы */
d[i] = s[i];
}
};

o7.exit_code = 0;
Expand Down
43 changes: 26 additions & 17 deletions source/GeneratorJs.mod
Expand Up @@ -892,10 +892,8 @@ PROCEDURE Expression(VAR gen: Generator; expr: Ast.Expression; set: SET);
i := last;
WHILE i > 0 DO
CASE arr[i].add OF
Scanner.Minus:
Text.Str(gen, sub)
| Scanner.Plus:
Text.Str(gen, add)
Scanner.Minus: Text.Str(gen, sub)
| Scanner.Plus : Text.Str(gen, add)
END;
DEC(i)
END;
Expand All @@ -913,7 +911,11 @@ PROCEDURE Expression(VAR gen: Generator; expr: Ast.Expression; set: SET);
arr[last] := sum;
sum := sum.next
UNTIL sum = NIL;
GenArrOfAddOrSub(gen, arr, last, "o7.add(" , "o7.sub(");
IF arr[0].type.id IN Ast.Reals THEN
GenArrOfAddOrSub(gen, arr, last, "o7.fadd(", "o7.fsub(")
ELSE
GenArrOfAddOrSub(gen, arr, last, "o7.add(" , "o7.sub(")
END;
i := 0;
WHILE i < last DO
INC(i);
Expand Down Expand Up @@ -969,14 +971,23 @@ PROCEDURE Expression(VAR gen: Generator; expr: Ast.Expression; set: SET);
arr[i] := term
END;
last := i;
WHILE i >= 0 DO
CASE arr[i].mult OF
Scanner.Asterisk : Text.Str(gen, "o7.mul(")
| Scanner.Div, Scanner.Slash
: Text.Str(gen, "o7.div(")
| Scanner.Mod : Text.Str(gen, "o7.mod(")
END;
DEC(i)
IF arr[i].type.id IN Ast.Integers THEN
WHILE i >= 0 DO
CASE arr[i].mult OF
Scanner.Asterisk : Text.Str(gen, "o7.mul(")
| Scanner.Div : Text.Str(gen, "o7.div(")
| Scanner.Mod : Text.Str(gen, "o7.mod(")
END;
DEC(i)
END
ELSE
WHILE i >= 0 DO
CASE arr[i].mult OF
Scanner.Asterisk : Text.Str(gen, "o7.fmul(")
| Scanner.Slash : Text.Str(gen, "o7.fdiv(")
END;
DEC(i)
END
END;
Expression(gen, arr[0].factor, {});
i := 0;
Expand Down Expand Up @@ -2082,10 +2093,8 @@ BEGIN
IF o # NIL THEN
V.Init(o^);
GenOptions.Default(o^);
o.varInit := GenOptions.VarInitZero;
o.checkArith := TRUE & FALSE;

o.std := EcmaScript5;
o.varInit := GenOptions.VarInitZero;
o.std := EcmaScript5;

o.expectArray := FALSE
END
Expand Down
33 changes: 33 additions & 0 deletions test/source/Real.mod
Expand Up @@ -62,6 +62,39 @@ BEGIN
Out.Real(a, 0); Out.Ln
END Fail;

PROCEDURE FailAdd*;
VAR a, b: REAL;
BEGIN
a := 9.E+307;
b := 111.E+306;
Out.Real(a + b, 0); Out.Ln
END FailAdd;

PROCEDURE FailSub*;
VAR b: REAL;
BEGIN
b := 11.9E+307;
Out.Real(-7.E+307 - b, 0); Out.Ln
END FailSub;

PROCEDURE FailMul*;
VAR a: REAL;
BEGIN
IF 1 >= 0 THEN
a := 3.4E+170
END;
IF 0 < 111 THEN
Out.Real(a * 7.4E153, 0); Out.Ln
END
END FailMul;

PROCEDURE FailDiv*;
VAR a: REAL;
BEGIN
a := 0.E-123;
Out.Real(0.000000000 / a, 0); Out.Ln
END FailDiv;

PROCEDURE Go*;
VAR a, b, c: REAL;
BEGIN
Expand Down

0 comments on commit 5196e44

Please sign in to comment.