fixed bug in variable resolution and simplified the code

This commit is contained in:
Sander Hautvast 2021-03-01 20:15:23 +01:00
parent 34e58b193a
commit cf59d18887
2 changed files with 72 additions and 50 deletions

View file

@ -2,7 +2,7 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Interactive Linear Algebra</title> <title>MatRepl</title>
<link rel="stylesheet" href="src/css/app.css"> <link rel="stylesheet" href="src/css/app.css">
</head> </head>
<body> <body>

View file

@ -39,13 +39,13 @@ export const update_lazy_objects = function () {
let value = visit_expression(object.lazy_expression); let value = visit_expression(object.lazy_expression);
let existing_value = state[object.binding]; let existing_value = state[object.binding];
if (existing_value) { if (existing_value) {
update_vector_arrow(existing_value.object.id, value.object); update_vector_arrow(existing_value.id, value);
} }
state[object.binding].object.x0 = value.object.x0; state[object.binding].x0 = value.x0;
state[object.binding].object.y0 = value.object.y0; state[object.binding].y0 = value.y0;
state[object.binding].object.x = value.object.x; state[object.binding].x = value.x;
state[object.binding].object.y = value.object.y; state[object.binding].y = value.y;
state[object.binding].object.id = value.object.id; state[object.binding].id = value.id;
let description = state[object.binding].description; let description = state[object.binding].description;
if (!description) { if (!description) {
description = state[object.binding]; description = state[object.binding];
@ -105,17 +105,20 @@ const handle_enter = function () {
try { try {
result = visit_expression(statement); result = visit_expression(statement);
let object_wrapper = result.value !== undefined ? result.value : result; let object_wrapper = result.value !== undefined ? result.value : result;
object_wrapper.object.label = object_wrapper.binding; if (object_wrapper) {
if (object_wrapper.object.is_vector) { if (object_wrapper.is_object) {
if (object_wrapper.previous) { object_wrapper.label = object_wrapper.binding;
update_vector_arrow(object_wrapper.previous.id, object_wrapper.object); if (object_wrapper.is_vector) {
} else { if (object_wrapper.previous) {
vectors.push(object_wrapper.object); update_vector_arrow(object_wrapper.previous.id, object_wrapper);
} else {
vectors.push(object_wrapper);
add_vector_arrow_to_svg(object_wrapper.object); add_vector_arrow_to_svg(object_wrapper);
}
}
} }
} }
if (result.description) { if (result.description) {
result = result.description; result = result.description;
} }
@ -133,14 +136,22 @@ const visit_expression = function (expr) {
switch (expr.type) { switch (expr.type) {
case 'declaration': { case 'declaration': {
let value = visit_expression(expr.initializer); let value = visit_expression(expr.initializer);
if (!value.is_object) {
value = {
description: value,
get: function () {
return description; // description IS value in this case
}
};
}
value.binding = expr.var_name.value; value.binding = expr.var_name.value;
if (state[value.binding]) { if (state[value.binding]) {
value.previous = state[value.binding].object; value.previous = state[value.binding];
} }
state[value.binding] = value; state[value.binding] = value;
let description = state[value.binding].description; let description = state[value.binding].description;
if (!description) { if (!description) {
description = state[value.binding]; //questionable. use toString instead of message? description = value; // primitive value (eg number, string)
} }
update_lazy_objects(); update_lazy_objects();
return {description: expr.var_name.value + ':' + description, value: value}; return {description: expr.var_name.value + ':' + description, value: value};
@ -162,7 +173,7 @@ const visit_expression = function (expr) {
let right = visit_expression(expr.right); let right = visit_expression(expr.right);
switch (expr.operator) { switch (expr.operator) {
case token_types.MINUS: case token_types.MINUS:
return left - right; return subtract(left, right);
case token_types.PLUS: case token_types.PLUS:
return addition(left, right); return addition(left, right);
case token_types.STAR: case token_types.STAR:
@ -176,7 +187,7 @@ const visit_expression = function (expr) {
} }
case 'identifier': { case 'identifier': {
if (state[expr.name]) { if (state[expr.name]) {
return state[expr.name]; return state[expr.name].get();
} else { } else {
break; break;
} }
@ -215,16 +226,17 @@ const function_call = function (function_name, argument_exprs) {
const method_call = function (object_wrapper, method_or_property) { const method_call = function (object_wrapper, method_or_property) {
if (object_wrapper) { if (object_wrapper) {
if (method_or_property.type === 'call') { // method if (method_or_property.type === 'call') { // method
if (typeof object_wrapper.object[method_or_property.name] !== 'function') { if (typeof object_wrapper[method_or_property.name] !== 'function') {
throw {message: `method ${method_or_property.name} not found on ${object_wrapper.type}`}; throw {message: `method ${method_or_property.name} not found on ${object_wrapper.type}`};
} }
return object_wrapper.object[method_or_property.name].apply(object_wrapper, method_or_property.arguments);
return object_wrapper[method_or_property.name].apply(object_wrapper, method_or_property.arguments);
} else { // property } else { // property
if (!Object.prototype.hasOwnProperty.call(object_wrapper.object, [method_or_property.name])) { if (!Object.prototype.hasOwnProperty.call(object_wrapper, [method_or_property.name])) {
throw {message: `property ${method_or_property.name} not found on ${object_wrapper.type}`}; throw {message: `property ${method_or_property.name} not found on ${object_wrapper.type}`};
} }
return object_wrapper.object[method_or_property.name]; return object_wrapper[method_or_property.name];
} }
} else { } else {
throw {message: `not found: ${object_wrapper}`}; throw {message: `not found: ${object_wrapper}`};
@ -243,11 +255,8 @@ const functions = {
remove: (args) => { remove: (args) => {
if (Object.prototype.hasOwnProperty.call(args[0], ['binding'])) { if (Object.prototype.hasOwnProperty.call(args[0], ['binding'])) {
delete state[args[0].binding]; delete state[args[0].binding];
return remove_vector(args[0].object); // by binding value
} else {
return remove_vector(args[0]); // by index (@...)
} }
return remove_vector(args[0]);
}, },
} }
@ -261,43 +270,56 @@ const help = function () {
} }
const multiplication = function (left, right) { const multiplication = function (left, right) {
if (left.object && left.type === 'vector' && !right.object) {
return left.object.multiply(right); const multiply = function (vector, scalar) {
return create_vector({
x0: vector.x0 * scalar,
y0: vector.y0 * scalar,
x: vector.x * scalar,
y: vector.y * scalar
});
};
if (left && left.type === 'vector' && !right) {
return multiply(left, right);
} }
if (right.object && right.type === 'vector' && !left.object) { if (right && right.type === 'vector' && !left) {
return right.object.multiply(left); return multiply(right, left);
} }
return left * right; return left * right;
} }
const addition = function (left, right) { const addition = function (left, right) {
if (left.object && left.type === 'vector' && right.object && right.type === 'vector') { if (left && left.type === 'vector' && right && right.type === 'vector') {
return left.object.add(right.object); return create_vector({
x0: left.x0 + right.x0,
y0: left.x0 + right.x0,
x: left.x + right.x,
y: left.y + right.y
});
} }
return left + right; return left + right;
} }
const subtract = function (left, right) {
// if (left && left.type === 'vector' && right.object && right.type === 'vector') {
// return left.subtract(right);
// }
// return left - right;
}
export const create_vector = function (vector) { //rename to create_vector export const create_vector = function (vector) { //rename to create_vector
vector.id = vectors_index_sequence++; vector.id = vectors_index_sequence++;
vector.add = (other) => create_vector({ vector.is_object = true;
x0: vector.x0 + other.x0,
y0: vector.x0 + other.x0,
x: vector.x + other.x,
y: vector.y + other.y
});
vector.multiply = (scalar) => create_vector({
x0: vector.x0 * scalar,
y0: vector.y0 * scalar,
x: vector.x * scalar,
y: vector.y * scalar
});
vector.is_vector = true; vector.is_vector = true;
vector.type = () => 'vector'; vector.type = () => 'vector';
return { //object_wrapper vector.type = 'vector';
type: 'vector', vector.description = `vector@${vector.id}{x0:${vector.x0},y0:${vector.y0} x:${vector.x},y:${vector.y}}`;
object: vector,
description: `vector@${vector.id}{x0:${vector.x0},y0:${vector.y0} x:${vector.x},y:${vector.y}}`, vector.get = function () {
}; return this;
}
return vector;
} }