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">
<head>
<meta charset="UTF-8">
<title>Interactive Linear Algebra</title>
<title>MatRepl</title>
<link rel="stylesheet" href="src/css/app.css">
</head>
<body>

View file

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