<commit_before>module('users.timfelgentreff.experimental.assert').requires('users.timfelgentreff.babelsberg.constraintinterpreter').toRun(function() {

	JSLoader.loadJs(module('users.timfelgentreff.csp.underscore-min').uri());

	/***************************************************************
	 * Continuous asserts
	 ***************************************************************/

	// TODO: improve syntax of bbb.assert
	// TODO: multiple asserts and multiple variable interconnected
	// TODO: enable and disable AssertConstraints
	// TODO: integration with other solvers

	Error.subclass("ContinuousAssertError", {
		initialize: function ContinuousAssertError(msg) {
			if (Error.captureStackTrace) {
				Error.captureStackTrace(this, ContinuousAssertError);
			} else {
				this.stack = (new Error).stack || '';
			}
			this.message = msg;
		},
		name: "ContinuousAssertError"
	});

	Object.subclass("AssertSolver", {
		initialize: function(message) {
			this.message = message;
		},
	    isConstraintObject: function() { return true; },
	    always: function(opts, func) {
	    	//console.log("AssertSolver.always");
	        var ctx = opts.ctx;
	        func.varMapping = ctx;
	        var cobj = new Constraint(func, this);
	        cobj.addPrimitiveConstraint(new AssertSolver.Constraint(this, cobj));
			try {
				cobj.enable();
			} catch(e) {
				if(e instanceof ContinuousAssertError) {
					cobj.disable();
				}
				throw e;
			}
	        return cobj;
	    },
	    constraintVariableFor: function(value, ivarname, bbbCVar) {
	    	//console.log("AssertSolver.constraintVariableFor", value, ivarname, bbbCVar);
	    	return new AssertSolver.Variable(this, value, ivarname, bbbCVar);
	    },
	    solve: function() {
	    	//console.log("AssertSolver.solve");
	    	this.check();
	    },
	    check: function() {
	    	//console.log("AssertSolver.check");
	    	if(this.constraint && this.constraint.enabled && typeof this.constraint.predicate === "function")
	    		if(!this.constraint.predicate())
	    			throw new ContinuousAssertError(this.message);
	    },
	    weight: 10
	});

	Object.subclass("AssertSolver.Variable", {
		initialize: function(solver, value, ivarname, bbbCVar) {
	    	//console.log("AssertSolver.Variable.initialize");
			this.solver = solver;
			this.__val__ = value;
		},
	    isConstraintObject: function() { return true; },
	    toFulfill: function(assertPredicate) {
	    	//console.log("AssertSolver.Variable.toFulfill", assertPredicate);
	    	this.assertPredicate = assertPredicate;
	    },
	    suggestValue: function(value) {
	    	//console.log("AssertSolver.Variable.suggestValue", value);
			var prev = this.__val__;
	    	this.__val__ = value;
			try {
				this.solver.solve();
			} catch(e) {
				// revert value in case of a violated assertion
				if(e instanceof ContinuousAssertError) {
					this.__val__ = prev;
				}
				throw e;
			}
	    	return this.__val__;
	    },
	    value: function() {
	    	return this.__val__;
	    },
	    setReadonly: function(bool) {
	    	//console.log("AssertSolver.Variable.setReadonly", bool);
	    	this.readonly = bool;
	    },
	    isReadonly: function() {
	    	//console.log("AssertSolver.Variable.isReadonly");
	        return this.readonly;
	    },
	    cnEquals: function() {
	    	//console.log("AssertSolver.Variable.cnEquals");
	        return new AssertSolver.PrimitiveConstraint(this, arguments);
	    }
	});

	Object.subclass("AssertSolver.PrimitiveConstraint", {
	    isConstraintObject: function() { return true; },
	    initialize: function(variable, args) {
	    	//console.log("AssertSolver.PrimitiveConstraint.initialize", variable, args);
			this.enabled = false;
	    	this.solver = variable.solver;
	    },
	    enable: function() {
	    	//console.log("AssertSolver.PrimitiveConstraint.enable");
			this.enabled = true;
	    },
	    disable: function() {
	    	//console.log("AssertSolver.PrimitiveConstraint.disable");
			this.enabled = false;
	    }
	});

	Object.subclass("AssertSolver.Constraint", {
	    isConstraintObject: function() { return true; },
	    initialize: function(solver, bbbConstraint) {
	    	//console.log("AssertSolver.Constraint.initialize");
			this.enabled = false;
	    	this.solver = solver;
	    	this.solver.constraint = this;

	    	// extract predicate from bbbConstraint
	    	this.predicate = _.chain(bbbConstraint.constraintvariables)
	    		.map(function(variable) {
	    			return variable.externalVariables(this.solver);
	    		}, this)
	    		.find(function(externalVariable) {
	    			return typeof externalVariable.assertPredicate === "function";
	    		})
	    		.value()
	    		.assertPredicate;
	    },
	    enable: function() {
	    	//console.log("AssertSolver.Constraint.enable");
			this.enabled = true;
	    },
	    disable: function() {
	    	//console.log("AssertSolver.Constraint.disable");
			this.enabled = false;
	    }
	});

	Object.extend(Babelsberg.prototype, {
		assert: function(opts, func) {
			opts.solver = new AssertSolver(opts.message);
			opts.allowUnsolvableOperations = true;
			opts.allowTests = true;
			//opts.debugging = true;
	        this.always(opts, func);
		}
	});

	/***************************************************************
	 * Triggering
	 ***************************************************************/
	// TODO: queue triggered actions and process list after assignments are done

	AssertSolver.subclass("TriggerSolver", {
		initialize: function(callback) {
			this.callback = callback;
			this.triggeredOnce = false;
		},
	    always: function(opts, func) {
	    	//console.log("TriggerSolver.always");
	        var ctx = opts.ctx;
	        func.varMapping = ctx;
	        var cobj = new Constraint(func, this);
	        cobj.addPrimitiveConstraint(new AssertSolver.Constraint(this, cobj));
			cobj.enable();
	        return cobj;
	    },
	    solve: function() {
	    	//console.log("TriggerSolver.solve", this.constraint.predicate());
	    	if(this.constraint &&
				this.constraint.enabled &&
				typeof this.constraint.predicate === "function" &&
				!this.triggeredOnce
			) {
	    		if(this.constraint.predicate()) {
					this.triggeredOnce = true;
					this.constraint.disable();
	    			this.callback();
				} else {
					// resetOnFalse?
				}
			}
	    },
	    weight: 10
	});

	Object.extend(Babelsberg.prototype, {
		trigger: function(opts, func) {
			opts.solver = new TriggerSolver(opts.callback);
			opts.allowUnsolvableOperations = true;
			opts.allowTests = true;
			//opts.debugging = true;
	        this.always(opts, func);
		}
	});

	/***************************************************************
	 * Layer activation
	 ***************************************************************/

	AssertSolver.subclass("LayerActivationSolver", {
		initialize: function(layer) {
			this.layer = layer;
		},
	    always: function(opts, func) {
	    	//console.log("LayerActivationSolver.always");
	        var ctx = opts.ctx;
	        func.varMapping = ctx;
	        var cobj = new Constraint(func, this);
	        cobj.addPrimitiveConstraint(new AssertSolver.Constraint(this, cobj));
			cobj.enable();
	        return cobj;
	    },
	    solve: function() {
	    	//console.log("LayerActivationSolver.solve", this.constraint.predicate());
	    	if(this.constraint &&
				this.constraint.enabled &&
				typeof this.constraint.predicate === "function"
			) {
				var predicateFulfilled = this.constraint.predicate();
	    		if(predicateFulfilled && !this.layer.isGlobal()) {
	    			this.layer.beGlobal();
				} else  if(!predicateFulfilled && this.layer.isGlobal()) {
	    			this.layer.beNotGlobal();
				}
			}
	    },
	    weight: 10
	});

	// hotfix
	// instead of cop.GlobalLayers.removeAt(idx); just use standard conform splice method
	Object.extend(cop, {
		disableLayer: function(layer) {
			var idx = cop.GlobalLayers.indexOf(layer)
			if (idx < 0) return;
			cop.GlobalLayers.splice(idx, 1);
			cop.invalidateLayerComposition();
		},
	});

	Object.extend(Layer.prototype, {
		activeOn: function(opts, func) {
			opts.solver = new LayerActivationSolver(this);
			opts.allowUnsolvableOperations = true;
			opts.allowTests = true;
			//opts.debugging = true;
	        opts.solver.always(opts, func);

			return this;
		}
	});

	/***************************************************************
	 * Scoped constraints
	 ***************************************************************/
	Object.extend(Layer.prototype, {
		always: function(opts, func) {
			opts.postponeEnabling = !this.isGlobal();
			var cobj = bbb.always(opts, func);
			// add cobj to list of associated constraints
			this.constraintObjects = this.constraintObjects || [];
			this.constraintObjects.push(cobj);
		},
		_activate: function() {
			this.constraintObjects = this.constraintObjects || [];
			this.constraintObjects.forEach(function(cobj) {
				cobj.enable();
			});
		},
		_deactivate: function() {
			this.constraintObjects = this.constraintObjects || [];
			this.constraintObjects.forEach(function(cobj) {
				cobj.disable();
			});
		}
	});

var copWithLayers = cop.withLayers;
var copWithoutLayers = cop.withoutLayers;
var copEnableLayer = cop.enableLayer;
var copDisableLayer = cop.disableLayer;
Object.extend(cop, {
    /* Layer Activation */
    withLayers: function withLayers(layers, func) {
		layers.forEach(function(layer) { layer._activate(); });

        try {
            return copWithLayers.apply(this, arguments);
        } finally {
			layers.forEach(function(layer) { layer._deactivate(); });
        }
    },

	withoutLayers: function withoutLayers(layers, func) {
		layers.forEach(function(layer) { layer._deactivate(); });

        try {
            return copWithoutLayers.apply(this, arguments);
        } finally {
			layers.forEach(function(layer) { layer._activate(); });
        }
    },

    /* Global Layer Activation */
    enableLayer: function(layer) {
		layer._activate();
		return copEnableLayer.apply(this, arguments);
    },

    disableLayer: function(layer) {
		layer._deactivate();
		return copDisableLayer.apply(this, arguments);
	}
});

});
<commit_msg>scoped assertions and triggers<commit_after>module('users.timfelgentreff.experimental.assert').requires('users.timfelgentreff.babelsberg.constraintinterpreter').toRun(function() {

	JSLoader.loadJs(module('users.timfelgentreff.csp.underscore-min').uri());

	/***************************************************************
	 * Continuous asserts
	 ***************************************************************/

	// TODO: improve syntax of bbb.assert
	// TODO: multiple asserts and multiple variable interconnected
	// TODO: enable and disable AssertConstraints
	// TODO: integration with other solvers

	Error.subclass("ContinuousAssertError", {
		initialize: function ContinuousAssertError(msg) {
			if (Error.captureStackTrace) {
				Error.captureStackTrace(this, ContinuousAssertError);
			} else {
				this.stack = (new Error).stack || '';
			}
			this.message = msg;
		},
		name: "ContinuousAssertError"
	});

	Object.subclass("AssertSolver", {
		initialize: function(message) {
			this.message = message;
		},
	    isConstraintObject: function() { return true; },
	    always: function(opts, func) {
	    	//console.log("AssertSolver.always");
	        var ctx = opts.ctx;
	        func.varMapping = ctx;
	        var cobj = new Constraint(func, this);
	        cobj.addPrimitiveConstraint(new AssertSolver.Constraint(this, cobj));
			try {
				if(!opts.postponeEnabling) { cobj.enable(); }
			} catch(e) {
				if(e instanceof ContinuousAssertError) {
					cobj.disable();
				}
				throw e;
			}
	        return cobj;
	    },
	    constraintVariableFor: function(value, ivarname, bbbCVar) {
	    	//console.log("AssertSolver.constraintVariableFor", value, ivarname, bbbCVar);
	    	return new AssertSolver.Variable(this, value, ivarname, bbbCVar);
	    },
	    solve: function() {
	    	//console.log("AssertSolver.solve");
	    	this.check();
	    },
	    check: function() {
	    	//console.log("AssertSolver.check");
	    	if(this.constraint && this.constraint.enabled && typeof this.constraint.predicate === "function")
	    		if(!this.constraint.predicate())
	    			throw new ContinuousAssertError(this.message);
	    },
	    weight: 10
	});

	Object.subclass("AssertSolver.Variable", {
		initialize: function(solver, value, ivarname, bbbCVar) {
	    	//console.log("AssertSolver.Variable.initialize");
			this.solver = solver;
			this.__val__ = value;
		},
	    isConstraintObject: function() { return true; },
	    toFulfill: function(assertPredicate) {
	    	//console.log("AssertSolver.Variable.toFulfill", assertPredicate);
	    	this.assertPredicate = assertPredicate;
	    },
	    suggestValue: function(value) {
	    	//console.log("AssertSolver.Variable.suggestValue", value);
			var prev = this.__val__;
	    	this.__val__ = value;
			try {
				this.solver.solve();
			} catch(e) {
				// revert value in case of a violated assertion
				if(e instanceof ContinuousAssertError) {
					this.__val__ = prev;
				}
				throw e;
			}
	    	return this.__val__;
	    },
	    value: function() {
	    	return this.__val__;
	    },
	    setReadonly: function(bool) {
	    	//console.log("AssertSolver.Variable.setReadonly", bool);
	    	this.readonly = bool;
	    },
	    isReadonly: function() {
	    	//console.log("AssertSolver.Variable.isReadonly");
	        return this.readonly;
	    },
	    cnEquals: function() {
	    	//console.log("AssertSolver.Variable.cnEquals");
	        return new AssertSolver.PrimitiveConstraint(this, arguments);
	    }
	});

	Object.subclass("AssertSolver.PrimitiveConstraint", {
	    isConstraintObject: function() { return true; },
	    initialize: function(variable, args) {
	    	//console.log("AssertSolver.PrimitiveConstraint.initialize", variable, args);
			this.enabled = false;
	    	this.solver = variable.solver;
	    },
	    enable: function() {
	    	//console.log("AssertSolver.PrimitiveConstraint.enable");
			this.enabled = true;
	    },
	    disable: function() {
	    	//console.log("AssertSolver.PrimitiveConstraint.disable");
			this.enabled = false;
	    }
	});

	Object.subclass("AssertSolver.Constraint", {
	    isConstraintObject: function() { return true; },
	    initialize: function(solver, bbbConstraint) {
	    	//console.log("AssertSolver.Constraint.initialize");
			this.enabled = false;
	    	this.solver = solver;
	    	this.solver.constraint = this;

	    	// extract predicate from bbbConstraint
	    	this.predicate = _.chain(bbbConstraint.constraintvariables)
	    		.map(function(variable) {
	    			return variable.externalVariables(this.solver);
	    		}, this)
	    		.find(function(externalVariable) {
	    			return typeof externalVariable.assertPredicate === "function";
	    		})
	    		.value()
	    		.assertPredicate;
	    },
	    enable: function() {
	    	//console.log("AssertSolver.Constraint.enable");
			this.enabled = true;
	    },
	    disable: function() {
	    	//console.log("AssertSolver.Constraint.disable");
			this.enabled = false;
	    }
	});

	Object.extend(Babelsberg.prototype, {
		assert: function(opts, func) {
			opts.solver = new AssertSolver(opts.message);
			opts.allowUnsolvableOperations = true;
			opts.allowTests = true;
			//opts.debugging = true;
	        return this.always(opts, func);
		}
	});

	/***************************************************************
	 * Triggering
	 ***************************************************************/
	// TODO: queue triggered actions and process list after assignments are done

	AssertSolver.subclass("TriggerSolver", {
		initialize: function(callback) {
			this.callback = callback;
			this.triggeredOnce = false;
		},
	    always: function(opts, func) {
	    	//console.log("TriggerSolver.always");
	        var ctx = opts.ctx;
	        func.varMapping = ctx;
	        var cobj = new Constraint(func, this);
	        cobj.addPrimitiveConstraint(new AssertSolver.Constraint(this, cobj));
			if(!opts.postponeEnabling) { cobj.enable(); }
	        return cobj;
	    },
	    solve: function() {
	    	//console.log("TriggerSolver.solve", this.constraint.predicate());
	    	if(this.constraint &&
				this.constraint.enabled &&
				typeof this.constraint.predicate === "function" &&
				!this.triggeredOnce
			) {
	    		if(this.constraint.predicate()) {
					this.triggeredOnce = true;
					this.constraint.disable();
	    			this.callback();
				} else {
					// resetOnFalse?
				}
			}
	    },
	    weight: 10
	});

	Object.extend(Babelsberg.prototype, {
		trigger: function(opts, func) {
			opts.solver = new TriggerSolver(opts.callback);
			opts.allowUnsolvableOperations = true;
			opts.allowTests = true;
			//opts.debugging = true;
	        return this.always(opts, func);
		}
	});

	/***************************************************************
	 * Layer activation
	 ***************************************************************/
	AssertSolver.subclass("LayerActivationSolver", {
		initialize: function(layer) {
			this.layer = layer;
		},
	    always: function(opts, func) {
	    	//console.log("LayerActivationSolver.always");
	        var ctx = opts.ctx;
	        func.varMapping = ctx;
	        var cobj = new Constraint(func, this);
	        cobj.addPrimitiveConstraint(new AssertSolver.Constraint(this, cobj));
			cobj.enable();
	        return cobj;
	    },
	    solve: function() {
	    	//console.log("LayerActivationSolver.solve", this.constraint.predicate());
	    	if(this.constraint &&
				this.constraint.enabled &&
				typeof this.constraint.predicate === "function"
			) {
				var predicateFulfilled = this.constraint.predicate();
	    		if(predicateFulfilled && !this.layer.isGlobal()) {
	    			this.layer.beGlobal();
				} else  if(!predicateFulfilled && this.layer.isGlobal()) {
	    			this.layer.beNotGlobal();
				}
			}
	    },
	    weight: 10
	});

	// hotfix
	// instead of cop.GlobalLayers.removeAt(idx); just use standard conform splice method
	Object.extend(cop, {
		disableLayer: function(layer) {
			var idx = cop.GlobalLayers.indexOf(layer)
			if (idx < 0) return;
			cop.GlobalLayers.splice(idx, 1);
			cop.invalidateLayerComposition();
		},
	});

	Object.extend(Layer.prototype, {
		activeOn: function(opts, func) {
			opts.solver = new LayerActivationSolver(this);
			opts.allowUnsolvableOperations = true;
			opts.allowTests = true;
			//opts.debugging = true;
	        opts.solver.always(opts, func);

			return this;
		}
	});

	/***************************************************************
	 * Scoped constraints
	 ***************************************************************/
	Object.extend(Layer.prototype, {
		always: function(opts, func) {
			opts.postponeEnabling = !this.isGlobal();
			var cobj = bbb.always(opts, func);

			this.constraintObjects = this.constraintObjects || [];
			this.constraintObjects.push(cobj);
		},
		assert: function(opts, func) {
			opts.postponeEnabling = !this.isGlobal();
			var cobj = bbb.assert(opts, func);

			this.constraintObjects = this.constraintObjects || [];
			this.constraintObjects.push(cobj);
		},
		trigger: function(opts, func) {
			opts.postponeEnabling = !this.isGlobal();
			var cobj = bbb.trigger(opts, func);

			this.constraintObjects = this.constraintObjects || [];
			this.constraintObjects.push(cobj);
		},
		_activate: function() {
			this.constraintObjects = this.constraintObjects || [];
			this.constraintObjects.forEach(function(cobj) {
				cobj.enable();
			});
		},
		_deactivate: function() {
			this.constraintObjects = this.constraintObjects || [];
			this.constraintObjects.forEach(function(cobj) {
				cobj.disable();
			});
		}
	});

	var copWithLayers = cop.withLayers;
	var copWithoutLayers = cop.withoutLayers;
	var copEnableLayer = cop.enableLayer;
	var copDisableLayer = cop.disableLayer;
	Object.extend(cop, {
		/* Layer Activation */
		withLayers: function withLayers(layers, func) {
			layers.forEach(function(layer) { layer._activate(); });

			try {
				return copWithLayers.apply(this, arguments);
			} finally {
				layers.forEach(function(layer) { layer._deactivate(); });
			}
		},

		withoutLayers: function withoutLayers(layers, func) {
			layers.forEach(function(layer) { layer._deactivate(); });

			try {
				return copWithoutLayers.apply(this, arguments);
			} finally {
				layers.forEach(function(layer) { layer._activate(); });
			}
		},

		/* Global Layer Activation */
		enableLayer: function(layer) {
			layer._activate();
			return copEnableLayer.apply(this, arguments);
		},

		disableLayer: function(layer) {
			layer._deactivate();
			return copDisableLayer.apply(this, arguments);
		}
	});

});
<|endoftext|>


<commit_before>"use strict";

// A lambda calculus interpreter
// =============================
//
// * [The essence of functional programming](http://page.mi.fu-berlin.de/scravy/realworldhaskell/materialien/the-essence-of-functional-programming.pdf) by Philip Wadler
// * [Structuring functional programs by using monads](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.39.3974) by Davor Obradovic
//

const expect = require('expect.js'),
  __ = require('../lib/kansuu.js'),
  math = require('../lib/kansuu-math.js'),
  Array = require('../lib/kansuu-array.js'),
  ID = require('../lib/kansuu.js').monad.identity,
  String = require('../lib/kansuu-string.js'),
  Pair = require('../lib/kansuu.js').pair,
  Maybe = require('../lib/kansuu.js').monad.maybe,
  List = require('../lib/kansuu.js').monad.list,
  Parser = require('../lib/kansuu.js').monad.parser;

// ### environment
// ~~~haskell
// type Environment = List[(Name, Value)]
// ~~~
const Env = {
  // ## 空の環境
  empty: (variable) => {
    return Maybe.nothing(variable);
  },
  /* 変数名に対応する値を環境から取りだす */
  lookup: (identifier, env) => {
    expect(identifier).to.a('string');
    return env(identifier);
  },
  /* 環境を拡張する */
  // extend:: Pair[String,Any] => FUN[]
  extend: (pair, oldEnv) => {
    return Pair.match(pair,{
      empty: (_) => {
        return Maybe.nothing(_);
      },
      cons: (identifier, value) => {
        expect(identifier).to.a('string');
        return (queryIdentifier) => {
          expect(queryIdentifier).to.a('string');
          if(identifier === queryIdentifier) {
            return Maybe.just(value);
          } else {
            return Env.lookup(queryIdentifier,oldEnv);
          }
        };
      }
    });
    // const identifier = Pair.left(pair);
    // const value = Pair.right(pair);
  }
};

// Syntax
// s-expression : atom
//              | "(" s-expression ")"
//              | list
// list         : "(" s-expression <s-expression> ")"
// atom         | letter atom-part
// atom-part    : empty
//              | letter atom-part
//              | number atom-part
// letter       | [a-zA-Z]
// number       | [0-9]
// empty        | " "
const Syntax = {
  s_exp: () => {
    return Parser.append(
      Syntax.atom()
    )(
      Parser.append(
        Parser.bracket(
          Parser.char("("),
          (() => {
            return Syntax.s_exp();
          }),
          Parser.char(")"))
      )(
        Syntax.list()
      )
    );
  },
  list: () => {
    return Parser.bracket(
      Parser.char("("),
      () => {
        return Parser.many(Syntax.s_exp());
      },
      Parser.char(")")
    )
  },
  atom: () => {
    return Parser.token(Parser.alt(
      Parser.numeric(),
      Parser.alt(
        Syntax.bool(),
        Parser.alt(
          Parser.ident(),
          Parser.alt(
            Syntax.operator(),
            Parser.string())))));
    // return Parser.append(
    //   Parser.token(Parser.ident())
    // )( // numeric
    //   Parser.append(
    //     Parser.token(Parser.numeric())
    //   )( // string
    //     Parser.append(
    //       Parser.token(Parser.flatMap(Parser.string())(string => {
    //         return Parser.unit(string);
    //       }))
    //     )(
    //       Syntax.bool()
    //     )
    //   )
    // );
    // return Parser.flatMap(Parser.letter())(c => {
    //   return Parser.flatMap(Syntax.atom_part())(part => {
    //     const letter = List.toString(c);
    //     return Parser.unit(c + part);
    //   })
    // })
  },
  operator: () => {
    const isOperator = (x) => {
      // if(x.match(/[+\-*\/]/)){
      if(buildinOperators[x]){
        return true;
      } else {
        return false;
      }
    };
    return Parser.sat(isOperator);
  },
  bool: () => {
    return Parser.append(
      Parser.token(Parser.flatMap(Parser.chars("#t"))(_ => {
        return Parser.unit(true);
      }))
    )(
      Parser.token(Parser.flatMap(Parser.chars("#f"))(_ => {
        return Parser.unit(false);
      }))
    );
  }
};

const buildin = {
  operators: {
    "+": math.add,
    "-": math.subtract,
    "*": math.multiply,
    "/": math.divide
  },
  functions: {
    "add": math.add,
    "subtract": math.subtract,
    "multiply": math.multiply,
    "divide": math.divide,
    "not": __.not(__.id),
    "numberp": (arg) => {
      return (__.typeOf(arg) === 'number');
    }
  }
};

const buildinOperators = {
  "+": math.add,
  "-": math.subtract,
  "*": math.multiply,
  "/": math.divide
};

const buildinFunctions = {
  "add": math.add,
  "subtract": math.subtract,
  "multiply": math.multiply,
  "divide": math.divide,
  "not": __.not(__.id),
  "numberp": (arg) => {
    return (__.typeOf(arg) === 'number');
  }
};

// ## Evaluator
const Evaluator = {
  applyOperator: (op,args) => {
    return (environment) => {
      const ops = {
        "+": math.add,
        "-": math.subtract,
        "*": math.multiply,
        "/": math.divide
      };
      const operator = ops[op];
      return Array.foldl1(args)(N => {
        return (M) => {
          return Maybe.flatMap(M)(m => {
            return Maybe.flatMap(N)(n => {
              return Maybe.just(operator(n)(m));
            });
          });
        };
      });
    };
  },
  // ### Evaluator#evaluate
  evaluate: (exp) => {
    return (environment) => {
      if(__.typeOf(exp) === 'array') {
        // operator application
        if(Array.isEmpty(exp) === true) {
          return ID.unit(Maybe.nothing());
          // return ID.unit(Maybe.just([]));
        } else {
          const head = Array.head(exp),
            tail = Array.tail(exp);
          if(buildin.operators[head]){
            const actualArgs = Array.map(tail)(__.flip(Evaluator.evaluate)(environment));
            return ID.unit(
              Evaluator.applyOperator(head, actualArgs)(environment)
            );
          }
          if(buildin.functions[head]){
            const actualArgs = Array.map(tail)(__.flip(Evaluator.evaluate)(environment));
            return ID.unit(
              Evaluator.applyFunction(head, actualArgs)(environment)
            );
          }
          return ID.unit(Maybe.nothing());
        }
        return ID.unit(Maybe.just(exp));
      } else {
        return ID.unit(Maybe.just(exp));
      }
      // return Exp.match(exp, {
      //   fail: (_) => {
      //     return ID.unit(Maybe.nothing());
      //   },
      //   variable: (name) => {
      //     return ID.unit(Env.lookup(name, environment));
      //   },
      //   number: (n) => {
      //     expect(n).to.a('number');
      //     return ID.unit(Maybe.just(n));
      //   },
      //   bool: (value) => {
      //     expect(value).to.a('boolean');
      //     return ID.unit(Maybe.just(value));
      //   },
      //   succ: (exp)=> {
      //     return Maybe.flatMap(Evaluator.evaluate(exp)(environment))(n => {
      //       if(__.typeOf(n) === 'number') {
      //         return ID.unit(Maybe.just(n + 1));
      //       } else {
      //         return ID.unit(Maybe.nothing(n));
      //       }
      //     });
      //   },
      //   add: (expN,expM)=> {
      //     return Maybe.flatMap(Evaluator.evaluate(expN)(environment))(n => {
      //       return Maybe.flatMap(Evaluator.evaluate(expM)(environment))(m => {
      //         return ID.unit(Maybe.just(n + m));
      //       });
      //     });
      //   },
      //   lambda: (variable, bodyExp) => {
      //     return Exp.match(variable,{
      //       variable: (name) => {
      //         /* クロージャーを返す */
      //         return ID.unit(Maybe.just(
      //           (actualArg) => {
      //             const newEnv = Env.extend(Pair.cons(name, actualArg),environment);
      //             return Evaluator.evaluate(bodyExp)(newEnv);
      //           }
      //         ));
      //       }
      //     });
      //   },
      //   apply: (lambdaExp, arg) => {
      //     return Maybe.flatMap(Evaluator.evaluate(lambdaExp)(environment))(closure => {
      //       return Maybe.flatMap(Evaluator.evaluate(arg)(environment))(actualArg => {
      //         return ID.unit(closure(actualArg));
      //       });
      //     });
      //   }
      // });
    };
  },
};

// ## Exp
const Exp = {
  match : (exp, pattern) => {
    return exp(pattern);
  },
  add: (n, m) => {
    return (pattern) => {
      return pattern.add(n,m);
    };
  },
  fail: (_) => {
    return (pattern) => {
      return pattern.fail(_);
    };
  },
  number: (n) => {
    return (pattern) => {
      return pattern.number(n);
    };
  },
  string: (value) => {
    return (pattern) => {
      return pattern.string(value);
    };
  },
  bool: (value) => {
    return (pattern) => {
      return pattern.bool(value);
    };
  },
  atom: (value) => {
    return (pattern) => {
      return pattern.atom(value);
    };
  },
  list: (items) => {
    return (pattern) => {
      return pattern.list(items);
    };
  },
  variable: (name) => {
    return (pattern) => {
      return pattern.variable(name);
    };
  },
  succ: (n) => {
    return (pattern) => {
      return pattern.succ(n);
    };
  },
  lambda: (variable, exp) => {
    expect(variable).to.a('function');
    return (pattern) => {
      return pattern.lambda(variable, exp);
    };
  },
  apply: (rator,rand) => {
    return (pattern) => {
      return pattern.apply(rator, rand);
    };
  }
};

const Interpreter = {
  // interpret :: String => Maybe[Any]
  interpret: (source) => {
    const parseResults = Parser.parse(Syntax.s_exp())(source);
    if(Array.isEmpty(parseResults) === true) {
      return Maybe.nothing();
    }
    const result =  Array.head(parseResults),
      remaining = result.remaining,
      exp = result.value;

    if(String.isEmpty(remaining) === false) {
      return Maybe.nothing();
    }
    const answer = Evaluator.evaluate(exp)(Env.empty);
    return Maybe.match(answer, {
      nothing: (_) => {
        return "";
      },
      just: (value) => {
        return `${value}`;
      }
    });
  }
};

module.exports = {
  env: Env,
  evaluator: Evaluator,
  exp: Exp,
  syntax: Syntax,
  interpreter: Interpreter
};

<commit_msg>clean up interpreter<commit_after>"use strict";

// A lambda calculus interpreter
// =============================
//
// * [The essence of functional programming](http://page.mi.fu-berlin.de/scravy/realworldhaskell/materialien/the-essence-of-functional-programming.pdf) by Philip Wadler
// * [Structuring functional programs by using monads](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.39.3974) by Davor Obradovic
//

const expect = require('expect.js'),
  __ = require('../lib/kansuu.js'),
  math = require('../lib/kansuu-math.js'),
  Array = require('../lib/kansuu-array.js'),
  ID = require('../lib/kansuu.js').monad.identity,
  String = require('../lib/kansuu-string.js'),
  Pair = require('../lib/kansuu.js').pair,
  Maybe = require('../lib/kansuu.js').monad.maybe,
  List = require('../lib/kansuu.js').monad.list,
  Parser = require('../lib/kansuu.js').monad.parser;

// ### environment
// ~~~haskell
// type Environment = List[(Name, Value)]
// ~~~
const Env = {
  // ## 空の環境
  empty: (variable) => {
    return Maybe.nothing(variable);
  },
  /* 変数名に対応する値を環境から取りだす */
  lookup: (identifier, env) => {
    expect(identifier).to.a('string');
    return env(identifier);
  },
  /* 環境を拡張する */
  // extend:: Pair[String,Any] => FUN[]
  extend: (pair, oldEnv) => {
    return Pair.match(pair,{
      empty: (_) => {
        return Maybe.nothing(_);
      },
      cons: (identifier, value) => {
        expect(identifier).to.a('string');
        return (queryIdentifier) => {
          expect(queryIdentifier).to.a('string');
          if(identifier === queryIdentifier) {
            return Maybe.just(value);
          } else {
            return Env.lookup(queryIdentifier,oldEnv);
          }
        };
      }
    });
    // const identifier = Pair.left(pair);
    // const value = Pair.right(pair);
  }
};

// Syntax
// s-expression : atom
//              | "(" s-expression ")"
//              | list
// list         : "(" s-expression <s-expression> ")"
// atom         | letter atom-part
// atom-part    : empty
//              | letter atom-part
//              | number atom-part
// letter       | [a-zA-Z]
// number       | [0-9]
// empty        | " "
const Syntax = {
  s_exp: () => {
    return Parser.append(
      Syntax.atom()
    )(
      Parser.append(
        Parser.bracket(
          Parser.char("("),
          (() => {
            return Syntax.s_exp();
          }),
          Parser.char(")"))
      )(
        Syntax.list()
      )
    );
  },
  list: () => {
    return Parser.bracket(
      Parser.char("("),
      () => {
        return Parser.many(Syntax.s_exp());
      },
      Parser.char(")")
    )
  },
  atom: () => {
    return Parser.token(Parser.alt(
      Parser.numeric(),
      Parser.alt(
        Syntax.bool(),
        Parser.alt(
          Parser.ident(),
          Parser.alt(
            Syntax.operator(),
            Parser.string())))));
    // return Parser.append(
    //   Parser.token(Parser.ident())
    // )( // numeric
    //   Parser.append(
    //     Parser.token(Parser.numeric())
    //   )( // string
    //     Parser.append(
    //       Parser.token(Parser.flatMap(Parser.string())(string => {
    //         return Parser.unit(string);
    //       }))
    //     )(
    //       Syntax.bool()
    //     )
    //   )
    // );
    // return Parser.flatMap(Parser.letter())(c => {
    //   return Parser.flatMap(Syntax.atom_part())(part => {
    //     const letter = List.toString(c);
    //     return Parser.unit(c + part);
    //   })
    // })
  },
  operator: () => {
    const isOperator = (x) => {
      if(buildin.operators[x]){
        return true;
      } else {
        return false;
      }
    };
    return Parser.sat(isOperator);
  },
  bool: () => {
    return Parser.append(
      Parser.token(Parser.flatMap(Parser.chars("#t"))(_ => {
        return Parser.unit(true);
      }))
    )(
      Parser.token(Parser.flatMap(Parser.chars("#f"))(_ => {
        return Parser.unit(false);
      }))
    );
  }
};

const buildin = {
  operators: {
    "+": math.add,
    "-": math.subtract,
    "*": math.multiply,
    "/": math.divide
  },
  functions: {
    "add": math.add,
    "subtract": math.subtract,
    "multiply": math.multiply,
    "divide": math.divide,
    "not": __.not(__.id),
    "numberp": (arg) => {
      return (__.typeOf(arg) === 'number');
    }
  }
};

// ## Evaluator
const Evaluator = {
  applyOperator: (op,args) => {
    return (environment) => {
      const ops = {
        "+": math.add,
        "-": math.subtract,
        "*": math.multiply,
        "/": math.divide
      };
      const operator = ops[op];
      return Array.foldl1(args)(N => {
        return (M) => {
          return Maybe.flatMap(M)(m => {
            return Maybe.flatMap(N)(n => {
              return Maybe.just(operator(n)(m));
            });
          });
        };
      });
    };
  },
  // ### Evaluator#evaluate
  evaluate: (exp) => {
    return (environment) => {
      if(__.typeOf(exp) === 'array') {
        // operator application
        if(Array.isEmpty(exp) === true) {
          return ID.unit(Maybe.nothing());
          // return ID.unit(Maybe.just([]));
        } else {
          const head = Array.head(exp),
            tail = Array.tail(exp);
          if(buildin.operators[head]){
            const actualArgs = Array.map(tail)(__.flip(Evaluator.evaluate)(environment));
            return ID.unit(
              Evaluator.applyOperator(head, actualArgs)(environment)
            );
          }
          if(buildin.functions[head]){
            const actualArgs = Array.map(tail)(__.flip(Evaluator.evaluate)(environment));
            return ID.unit(
              Evaluator.applyFunction(head, actualArgs)(environment)
            );
          }
          return ID.unit(Maybe.nothing());
        }
        return ID.unit(Maybe.just(exp));
      } else {
        return ID.unit(Maybe.just(exp));
      }
      // return Exp.match(exp, {
      //   fail: (_) => {
      //     return ID.unit(Maybe.nothing());
      //   },
      //   variable: (name) => {
      //     return ID.unit(Env.lookup(name, environment));
      //   },
      //   number: (n) => {
      //     expect(n).to.a('number');
      //     return ID.unit(Maybe.just(n));
      //   },
      //   bool: (value) => {
      //     expect(value).to.a('boolean');
      //     return ID.unit(Maybe.just(value));
      //   },
      //   succ: (exp)=> {
      //     return Maybe.flatMap(Evaluator.evaluate(exp)(environment))(n => {
      //       if(__.typeOf(n) === 'number') {
      //         return ID.unit(Maybe.just(n + 1));
      //       } else {
      //         return ID.unit(Maybe.nothing(n));
      //       }
      //     });
      //   },
      //   add: (expN,expM)=> {
      //     return Maybe.flatMap(Evaluator.evaluate(expN)(environment))(n => {
      //       return Maybe.flatMap(Evaluator.evaluate(expM)(environment))(m => {
      //         return ID.unit(Maybe.just(n + m));
      //       });
      //     });
      //   },
      //   lambda: (variable, bodyExp) => {
      //     return Exp.match(variable,{
      //       variable: (name) => {
      //         /* クロージャーを返す */
      //         return ID.unit(Maybe.just(
      //           (actualArg) => {
      //             const newEnv = Env.extend(Pair.cons(name, actualArg),environment);
      //             return Evaluator.evaluate(bodyExp)(newEnv);
      //           }
      //         ));
      //       }
      //     });
      //   },
      //   apply: (lambdaExp, arg) => {
      //     return Maybe.flatMap(Evaluator.evaluate(lambdaExp)(environment))(closure => {
      //       return Maybe.flatMap(Evaluator.evaluate(arg)(environment))(actualArg => {
      //         return ID.unit(closure(actualArg));
      //       });
      //     });
      //   }
      // });
    };
  },
};

// ## Exp
const Exp = {
  match : (exp, pattern) => {
    return exp(pattern);
  },
  add: (n, m) => {
    return (pattern) => {
      return pattern.add(n,m);
    };
  },
  fail: (_) => {
    return (pattern) => {
      return pattern.fail(_);
    };
  },
  number: (n) => {
    return (pattern) => {
      return pattern.number(n);
    };
  },
  string: (value) => {
    return (pattern) => {
      return pattern.string(value);
    };
  },
  bool: (value) => {
    return (pattern) => {
      return pattern.bool(value);
    };
  },
  atom: (value) => {
    return (pattern) => {
      return pattern.atom(value);
    };
  },
  list: (items) => {
    return (pattern) => {
      return pattern.list(items);
    };
  },
  variable: (name) => {
    return (pattern) => {
      return pattern.variable(name);
    };
  },
  succ: (n) => {
    return (pattern) => {
      return pattern.succ(n);
    };
  },
  lambda: (variable, exp) => {
    expect(variable).to.a('function');
    return (pattern) => {
      return pattern.lambda(variable, exp);
    };
  },
  apply: (rator,rand) => {
    return (pattern) => {
      return pattern.apply(rator, rand);
    };
  }
};

const Interpreter = {
  // interpret :: String => Maybe[Any]
  interpret: (source) => {
    const parseResults = Parser.parse(Syntax.s_exp())(source);
    if(Array.isEmpty(parseResults) === true) {
      return Maybe.nothing();
    }
    const result =  Array.head(parseResults),
      remaining = result.remaining,
      exp = result.value;

    if(String.isEmpty(remaining) === false) {
      return Maybe.nothing();
    }
    const answer = Evaluator.evaluate(exp)(Env.empty);
    return Maybe.match(answer, {
      nothing: (_) => {
        return "";
      },
      just: (value) => {
        return `${value}`;
      }
    });
  }
};

module.exports = {
  env: Env,
  evaluator: Evaluator,
  exp: Exp,
  syntax: Syntax,
  interpreter: Interpreter
};

<|endoftext|>


<commit_before>'use strict';

const amino = require('../../main.js');

const gfx = new amino.AminoGfx();

gfx.start(function (err) {
    if (err) {
        console.log('Amino error: ' + err.message);
        return;
    }

    //root
    const root = gfx.createGroup();

    gfx.setRoot(root);

    //triangle
    const model1 = gfx.createModel();

    //showTriangle(model1);
    //showTriangles(model1);
    //showRect(model1);
    showQuad(model1);

    root.add(model1);

    //some info
    console.log('screen: ' + JSON.stringify(gfx.screen));
    console.log('window size: ' + this.w() + 'x' + this.h());
});

/**
 * Simplest model.
 */
function showTriangle(model) {
    model.vertices([
        0, 0, 0,
        100, 50, 0,
        200, 200, 0 ]);
}

/**
 * Many triangles.
 */
function showTriangles(model) {
    const count = 1000;
    const vertexCount = count * 3;
    const vertices = [];
    const w = gfx.w();
    const h = gfx.h();

    for (let i  = 0; i < vertexCount; i++) {
        vertices.push(Math.random() * w);
        vertices.push(Math.random() * h);
        vertices.push((Math.random() - 0.5) * 50);
    }

    model.vertices(vertices);
}

/**
 * Rectangle.
 */
function showRect(model) {
    const x = 0;
    const y = 0;
    const w = 200;
    const h = 200;

    model.vertices([
        //triangle 1
        x, y, 0,
        x + w, y, 0,
        x, y + w, 0,

        //triangle 2
        x + w, y, 0,
        x, y + h, 0,
        x + w, y + h, 0
    ]);
}

/**
 * Quad.
 */
function showQuad(model) {
    const x = 0;
    const y = 0;
    const w = 200;
    const h = 200;

    //Note: no sorting applied
    const points = [
        [Math.random() * w, Math.random() * h],
        [Math.random() * w, Math.random() * h],
        [Math.random() * w, Math.random() * h],
        [Math.random() * w, Math.random() * h]
    ];

    // 1) using vertex coordinates only
    /*
    model.vertices([
        //triangle 1
        x + points[0][0], y + points[0][1], 0,
        x + points[1][0], y + points[1][1], 0,
        x + points[2][0], y + points[2][1], 0,

        //triangle 2
        x + points[1][0], y + points[1][1], 0,
        x + points[2][0], y + points[2][1], 0,
        x + points[3][0], y + points[3][1], 0
    ]);
    */

    // 2) using index
    model.vertices([
        //quad points
        x + points[0][0], y + points[0][1], 0,
        x + points[1][0], y + points[1][1], 0,
        x + points[2][0], y + points[2][1], 0,
        x + points[3][0], y + points[3][1], 0
    ]);

    model.indices([
        0, 1, 2, 1, 2, 3
    ]);
}

//TODO texture<commit_msg>added cube model<commit_after>'use strict';

const amino = require('../../main.js');

const gfx = new amino.AminoGfx();

gfx.start(function (err) {
    if (err) {
        console.log('Amino error: ' + err.message);
        return;
    }

    //root
    const root = gfx.createGroup();

    gfx.setRoot(root);

    //triangle
    const model1 = gfx.createModel();

    //showTriangle(model1);
    //showTriangles(model1);
    //showRect(model1);
    //showQuad(model1);
    showCube(model1);

    root.add(model1);

    //some info
    console.log('screen: ' + JSON.stringify(gfx.screen));
    console.log('window size: ' + this.w() + 'x' + this.h());
});

/**
 * Simplest model.
 */
function showTriangle(model) {
    model.vertices([
        0, 0, 0,
        100, 50, 0,
        200, 200, 0 ]);
}

/**
 * Many triangles.
 */
function showTriangles(model) {
    const count = 1000;
    const vertexCount = count * 3;
    const vertices = [];
    const w = gfx.w();
    const h = gfx.h();

    for (let i  = 0; i < vertexCount; i++) {
        vertices.push(Math.random() * w);
        vertices.push(Math.random() * h);
        vertices.push((Math.random() - 0.5) * 50);
    }

    model.vertices(vertices);
}

/**
 * Rectangle.
 */
function showRect(model) {
    const x = 0;
    const y = 0;
    const w = 200;
    const h = 200;

    model.vertices([
        //triangle 1
        x, y, 0,
        x + w, y, 0,
        x, y + w, 0,

        //triangle 2
        x + w, y, 0,
        x, y + h, 0,
        x + w, y + h, 0
    ]);
}

/**
 * Quad.
 */
function showQuad(model) {
    const x = 0;
    const y = 0;
    const w = 200;
    const h = 200;

    //Note: no sorting applied
    const points = [
        [Math.random() * w, Math.random() * h],
        [Math.random() * w, Math.random() * h],
        [Math.random() * w, Math.random() * h],
        [Math.random() * w, Math.random() * h]
    ];

    // 1) using vertex coordinates only
    /*
    model.vertices([
        //triangle 1
        x + points[0][0], y + points[0][1], 0,
        x + points[1][0], y + points[1][1], 0,
        x + points[2][0], y + points[2][1], 0,

        //triangle 2
        x + points[1][0], y + points[1][1], 0,
        x + points[2][0], y + points[2][1], 0,
        x + points[3][0], y + points[3][1], 0
    ]);
    */

    // 2) using index
    model.vertices([
        //quad points
        x + points[0][0], y + points[0][1], 0,
        x + points[1][0], y + points[1][1], 0,
        x + points[2][0], y + points[2][1], 0,
        x + points[3][0], y + points[3][1], 0
    ]);

    model.indices([
        0, 1, 2,
        1, 2, 3
    ]);
}

function showCube(model) {
    const x = 0;
    const y = 0;
    const w = 200;
    const h = 200;
    const d = 200;
    const dh = d / 2;

    model.vertices([
        x, y, -dh,
        x + w, y, -dh,
        x + w, y + h, -dh,
        x, y + h, -dh,

        x, y, dh,
        x + w, y, dh,
        x + w, y + h, dh,
        x, y + h, dh,
    ]);

    model.indices([
        //below
        0, 1, 2,
        0, 2, 3,

        //above
        4, 5, 6,
        4, 6, 7,

        //left
        0, 4, 7,
        0, 3, 7,

        //right
        1, 5, 6,
        1, 2, 6,

        //top
        0, 1, 5,
        0, 4, 5,

        //bottom
        2, 3, 7,
        2, 6, 7
    ]);

    model.opacity(.7);
    model.originX(.5).originY(.5);
    model.x(100).y(100);
    model.rx.anim().from(0).to(360).dur(5000).loop(-1).start();
    //model.rz.anim().from(0).to(360).dur(678).start();
}

//TODO texture<|endoftext|>


<commit_before>// ==UserScript==
// @name        toolset
// @namespace   samsquanchhunter14@gmail.com
// @include     http://aimgames.forummotion.com/
// @version     1.1
// @grant       none
// ==/UserScript==

//test thing

var css_string = "@import url(\'http://fonts.googleapis.com/css?family=Noto+Sans:400,700\');.box{width: 0px;height: 0px;position: relative;border: 0px solid #BBB;background: #EEE;font-family: \'Noto Sans\', sans-serif}.ribbon{width: 200px;background: #e43;position: absolute;top: 0px;left: -10px;text-align: center;line-height: 50px;letter-spacing: 1px;color: #ff0000;font-size: 18px}.ribbon span{width: 200px;background: #e43;position: absolute;top: 25px;left: -50px;text-align: center;line-height: 50px;letter-spacing: 1px;color: #f0f0f0;transform: rotate(-45deg);-webkit-transform: rotate(-45deg);font-size: 18px}.ribbon span::before{content: \"\";position:absolute;left:0px;top:100%;z-index:-1;border-left:3px solid #8F0808;border-right:3px solid transparent;border-bottom:3px solid transparent;border-top:3px solid #8F0808}.ribbon span::after{content:\"\";position:absolute;right:0px;top:100%;z-index:-1;border-left:3px solid transparent;border-right:3px solid #8F0808;border-bottom:3px solid transparent;border-top:3px solid #8F0808}";

var preva = "";
function get_new_msg() { //do we have a new msg
  if (document.getElementById("frame_chatbox").contentWindow.document.getElementById("chatbox").innerHTML != preva) {
    preva = document.getElementById("frame_chatbox").contentWindow.document.getElementById("chatbox").innerHTML;
    return true;
  } else {
    preva = document.getElementById("frame_chatbox").contentWindow.document.getElementById("chatbox").innerHTML;
    return false;
  }
}

var new_msgs = 0; //how many new msgs
function get_new_msgs() {
  if (getScrollTop() < 1600) {
    if (get_new_msg()) {
      new_msgs++;
      box_div.innerHTML =  '

' + new_msgs + ' new msgs

';
    }
  } else if (new_msgs != 0) {
    new_msgs = 0;
    box_div.innerHTML = '

';
  }
  //print(new_msgs);
}

function check_em() {
  document.getElementById("frame_chatbox").contentWindow.
  document.getElementById("chatbox").innerHTML = document.getElementById("frame_chatbox").contentWindow.
  document.getElementById("chatbox").innerHTML.
  replace(/\:11\]/g,
          '\:11\] CHECK \'EM');
  replace(/\:22\]/g,
          '\:22\] CHECK \'EM');
  replace(/\:33\]/g,
          '\:33\] CHECK \'EM');
  replace(/\:44\]/g,
          '\:44\] CHECK \'EM');
  replace(/\:55\]/g,
          '\:55\] CHECK \'EM');
  replace(/\:66\]/g,
          '\:66\] CHECK \'EM');
  replace(/\:77\]/g,
          '\:77\] CHECK \'EM');
  replace(/\:88\]/g,
          '\:88\] CHECK \'EM');
  replace(/\:99\]/g,
          '\:99\] CHECK \'EM');
  replace(/\:00\]/g,
          '\:00\] CHECK \'EM');

}

var gstyle;
function inject_css(css) {
    var head;
    head = document.getElementsByTagName('head')[0];
    if (!head) { return; }
    gstyle = document.createElement('style');
    gstyle.type = 'text/css';
    gstyle.innerHTML = css;
    head.appendChild(gstyle);
}

function getScrollTop() { //// http://stackoverflow.com/questions/6691558/how-do-i-make-a-div-follow-me-as-i-scroll-down-the-page
    if (typeof window.pageYOffset !== 'undefined' ) {
      // Most browsers
      return window.pageYOffset;
    }

    var d = document.documentElement;
    if (d.clientHeight) {
      // IE in standards mode
      return d.scrollTop;
    }

    // IE in quirks mode
    return document.body.scrollTop;
}

var visibleY = function(el){
    var top = el.getBoundingClientRect().top, rect, el = el.parentNode;
    do {
        rect = el.getBoundingClientRect();
        if (top <= rect.bottom === false)
            return false;
        el = el.parentNode;
    } while (el != document.body);
    // Check its within the document viewport
    return top <= document.documentElement.clientHeight;
};

var box_div; //init the box div so it can go anywhere
window.onload = function() {
  // inject our css
  inject_css(css_string);

  // make an empty div where the box will go
  var over_div = document.body;
  box_div = over_div.appendChild(document.createElement('div'));
  box_div.innerHTML =  '

';

  // get the count of new msgs
  setInterval(get_new_msgs, 500);

  window.onscroll = function() {
    //make the box scroll with the screen
    var box = document.getElementById('box'),
    scroll = getScrollTop();

    if (box !== null) {
      if (scroll <= 28) {
        box.style.top = "30px";
      } else {
        box.style.top = (scroll + 2) + "px";
      }
    }

    //reset the msgs if scrolled to the cbox
    if (visibleY(document.getElementById("frame_chatbox"))) {
      is_at_cbox = true;
    } else {
      is_at_cbox = false;
    }
  };

}
// += works too
<commit_msg>make sure preva != "" when returning true<commit_after>// ==UserScript==
// @name        toolset
// @namespace   samsquanchhunter14@gmail.com
// @include     http://aimgames.forummotion.com/*
// @version     1.1
// @grant       none
// ==/UserScript==

//test thing

var css_string = "@import url(\'http://fonts.googleapis.com/css?family=Noto+Sans:400,700\');.box{width: 0px;height: 0px;position: relative;border: 0px solid #BBB;background: #EEE;font-family: \'Noto Sans\', sans-serif}.ribbon{width: 200px;background: #e43;position: absolute;top: 0px;left: -10px;text-align: center;line-height: 50px;letter-spacing: 1px;color: #ff0000;font-size: 18px}.ribbon span{width: 200px;background: #e43;position: absolute;top: 25px;left: -50px;text-align: center;line-height: 50px;letter-spacing: 1px;color: #f0f0f0;transform: rotate(-45deg);-webkit-transform: rotate(-45deg);font-size: 18px}.ribbon span::before{content: \"\";position:absolute;left:0px;top:100%;z-index:-1;border-left:3px solid #8F0808;border-right:3px solid transparent;border-bottom:3px solid transparent;border-top:3px solid #8F0808}.ribbon span::after{content:\"\";position:absolute;right:0px;top:100%;z-index:-1;border-left:3px solid transparent;border-right:3px solid #8F0808;border-bottom:3px solid transparent;border-top:3px solid #8F0808}";

var preva = "";
function get_new_msg() { //do we have a new msg
  if (document.getElementById("frame_chatbox").contentWindow.document.getElementById("chatbox").innerHTML != preva && preva != "") {
    preva = document.getElementById("frame_chatbox").contentWindow.document.getElementById("chatbox").innerHTML;
    return true;
  } else {
    preva = document.getElementById("frame_chatbox").contentWindow.document.getElementById("chatbox").innerHTML;
    return false;
  }
}

var new_msgs = 0; //how many new msgs
function get_new_msgs() {
  if (getScrollTop() < 1600) {
    if (get_new_msg()) {
      new_msgs++;
      box_div.innerHTML =  '

' + new_msgs + ' new msgs

';
    }
  } else if (new_msgs != 0) {
    new_msgs = 0;
    box_div.innerHTML = '

';
  }
  //print(new_msgs);
}

function check_em() {
  document.getElementById("frame_chatbox").contentWindow.
  document.getElementById("chatbox").innerHTML = document.getElementById("frame_chatbox").contentWindow.
  document.getElementById("chatbox").innerHTML.
  replace(/\:11\]/g,
          '\:11\] CHECK \'EM');
  replace(/\:22\]/g,
          '\:22\] CHECK \'EM');
  replace(/\:33\]/g,
          '\:33\] CHECK \'EM');
  replace(/\:44\]/g,
          '\:44\] CHECK \'EM');
  replace(/\:55\]/g,
          '\:55\] CHECK \'EM');
  replace(/\:66\]/g,
          '\:66\] CHECK \'EM');
  replace(/\:77\]/g,
          '\:77\] CHECK \'EM');
  replace(/\:88\]/g,
          '\:88\] CHECK \'EM');
  replace(/\:99\]/g,
          '\:99\] CHECK \'EM');
  replace(/\:00\]/g,
          '\:00\] CHECK \'EM');

}

var gstyle;
function inject_css(css) {
    var head;
    head = document.getElementsByTagName('head')[0];
    if (!head) { return; }
    gstyle = document.createElement('style');
    gstyle.type = 'text/css';
    gstyle.innerHTML = css;
    head.appendChild(gstyle);
}

function getScrollTop() { //// http://stackoverflow.com/questions/6691558/how-do-i-make-a-div-follow-me-as-i-scroll-down-the-page
    if (typeof window.pageYOffset !== 'undefined' ) {
      // Most browsers
      return window.pageYOffset;
    }

    var d = document.documentElement;
    if (d.clientHeight) {
      // IE in standards mode
      return d.scrollTop;
    }

    // IE in quirks mode
    return document.body.scrollTop;
}

var visibleY = function(el){
    var top = el.getBoundingClientRect().top, rect, el = el.parentNode;
    do {
        rect = el.getBoundingClientRect();
        if (top <= rect.bottom === false)
            return false;
        el = el.parentNode;
    } while (el != document.body);
    // Check its within the document viewport
    return top <= document.documentElement.clientHeight;
};

var box_div; //init the box div so it can go anywhere
window.onload = function() {
  // inject our css
  inject_css(css_string);

  // make an empty div where the box will go
  var over_div = document.body;
  box_div = over_div.appendChild(document.createElement('div'));
  box_div.innerHTML =  '

';

  // get the count of new msgs
  setInterval(get_new_msgs, 500);

  window.onscroll = function() {
    //make the box scroll with the screen
    var box = document.getElementById('box'),
    scroll = getScrollTop();

    if (box !== null) {
      if (scroll <= 28) {
        box.style.top = "30px";
      } else {
        box.style.top = (scroll + 2) + "px";
      }
    }

    //reset the msgs if scrolled to the cbox
    if (visibleY(document.getElementById("frame_chatbox"))) {
      is_at_cbox = true;
    } else {
      is_at_cbox = false;
    }
  };

}
// += works too
<|endoftext|>


<commit_before>import _ from 'lodash';
import React, { Component } from 'react';
import Websocket from './websocket';
import AutoLinkText from 'react-autolink-text';

/*
 * Stolen from:
 * https://gist.github.com/mathewbyrne/1280286
 *
 *
 * TODO: Read thru this, instead, & see if we should use something like it.
 * https://github.com/raineroviir/react-redux-socketio-chat/blob/master/src/common/containers/ChatContainer.js
 *
 *
 */
function slugify(text)
{
  return text.toString().toLowerCase()
    .replace(/\s+/g, '-')           // Replace spaces with -
    .replace(/[^\w\-]+/g, '')       // Remove all non-word chars
    .replace(/\-\-+/g, '-')         // Replace multiple - with single -
    .replace(/^-+/, '')             // Trim - from start of text
    .replace(/-+$/, '');            // Trim - from end of text
}

/*
 * If the given text contains a link to a youtube video, this function
 * will parse the text and extract two bits of data:
 *
 * 1. The video URL, and
 * 2. The video ID.
 *
 * If matched, this function returns an object of the form:
 *
 *  {
 *      videoId: '...',
 *      embedUrl: '...',
 *  }
 *
 * Otherwise, it returns a false value.
 *
 * This current works for both short, and long share urls:
 * - https://www.youtube.com/watch?v=fd6clpIvrfg
 * - https://youtu.be/fd6clpIvrfg
 */
function extractVideo(text) {
    let result = false;
    let videoId = null;
    let videoLink = null;
    const short_re = /https:\/\/youtu.be\/(\w+)/;
    const long_re = /https:\/\/www.youtube.com\/watch\?v=(\w+)/;

    if(short_re.test(text)) {
        // Note: returns ["https://youtu.be/fd6clpIvrfg", "fd6clpIvrfg"]
        [videoLink, videoId] = short_re.exec(text);
        result = {
            videoId: videoId,
            videoLink: videoLink,
            embedUrl: "https://www.youtube.com/embed/" + videoId
        }
    }
    else if(long_re.test(text)) {
        [videoLink, videoId] = long_re.exec(text);
        result = {
            videoId: videoId,
            videoLink: videoLink,
            embedUrl: "https://www.youtube.com/embed/" + videoId
        }
    }
    console.log("Video Extraction result: ", result);
    return result;
}

export default class Chat extends Component {

    constructor(props) {
        super(props);
        this.state = {
            messages: [],
            current: '',
        }
        this.onFormSubmit.bind(this);
    }

    handleMessage(data) {
        // NOTE: data should be an object of the form: {from: ..., message: ...}
        const new_message = {
            id: slugify(data.message) + new Date().valueOf(),  // ¯\_(ツ)_/¯
            text: data.message,
            from: data.from
        }
        const messages = _.concat(this.state.messages, [new_message]);
        this.setState({messages: messages, current: this.state.current});
        console.log('[handleMessage], this.state.current = ', this.state.current);
    }

    onFormSubmit(event) {
        event.preventDefault();
        // event.target is the form.
        // event.target[0] is the first child element (our <input>)
        const inputElement = event.target.children[0].children[0];
        const message = inputElement.value;
        console.log("[onFormSubmit] message = ", message);

        this.setState({messages: this.state.messages, current: message});

        console.log('[onFormSubmit], this.state.current = ', this.state.current);
        inputElement.value = ""; // clear the input.
    }

    renderMessageList() {
        return this.state.messages.map((msg) => {
            // A Reply is a message from the other user but not the system.
            const isReply = this.props.user.username !== msg.from && msg.from !== 'system';

            // Dont' show avatars for system messages.
            // TODO: replace this with the user's avatar.
            /*
            const avatar = (
                msg.from === "system" ? "" :
                person
            );
            */

            const chatClasses = (isReply ? 'chatBubble reply' : 'chatBubble') +
                (msg.from === 'system' ? ' notice' : '');

            // Inline links to youtube videos
            const video = extractVideo(msg.text);
            let content = msg.text;

            if(video) {
                content = (

                            <AutoLinkText text={msg.text} />

                );
            }
            else {
                content = (

                        <AutoLinkText text={msg.text} />

                );
            }

            return (

                    {content}

            );
        });
    }

    render() {

        /*
         * NOTE: this.props.user contains info about our user.
         *
         * TODO: tag replies from the other user with className: reply
         * TODO: tag notice messages with className: notice
         *
         */
        console.log('[render], this.state.current = ', this.state.current);
        return (

{this.renderMessageList()}

            <Websocket url={this.props.ws_url}
                       debug={true}
                       onMessage={this.handleMessage.bind(this)}
                       sendMessage={this.state.current} />
            <form onSubmit={this.onFormSubmit.bind(this)} className="chatForm">

                <input className="mdl-textfield__input"
                       type="text"
                       id="message"
                       name="message" />
                Your Message

              <button className="mdl-button mdl-js-button">Send</button>
            </form>

        );
    }
}
<commit_msg>adding chat avatars<commit_after>import _ from 'lodash';
import React, { Component } from 'react';
import Websocket from './websocket';
import AutoLinkText from 'react-autolink-text';

/*
 * Stolen from:
 * https://gist.github.com/mathewbyrne/1280286
 *
 *
 * TODO: Read thru this, instead, & see if we should use something like it.
 * https://github.com/raineroviir/react-redux-socketio-chat/blob/master/src/common/containers/ChatContainer.js
 *
 *
 */
function slugify(text)
{
  return text.toString().toLowerCase()
    .replace(/\s+/g, '-')           // Replace spaces with -
    .replace(/[^\w\-]+/g, '')       // Remove all non-word chars
    .replace(/\-\-+/g, '-')         // Replace multiple - with single -
    .replace(/^-+/, '')             // Trim - from start of text
    .replace(/-+$/, '');            // Trim - from end of text
}

/*
 * If the given text contains a link to a youtube video, this function
 * will parse the text and extract two bits of data:
 *
 * 1. The video URL, and
 * 2. The video ID.
 *
 * If matched, this function returns an object of the form:
 *
 *  {
 *      videoId: '...',
 *      embedUrl: '...',
 *  }
 *
 * Otherwise, it returns a false value.
 *
 * This current works for both short, and long share urls:
 * - https://www.youtube.com/watch?v=fd6clpIvrfg
 * - https://youtu.be/fd6clpIvrfg
 */
function extractVideo(text) {
    let result = false;
    let videoId = null;
    let videoLink = null;
    const short_re = /https:\/\/youtu.be\/(\w+)/;
    const long_re = /https:\/\/www.youtube.com\/watch\?v=(\w+)/;

    if(short_re.test(text)) {
        // Note: returns ["https://youtu.be/fd6clpIvrfg", "fd6clpIvrfg"]
        [videoLink, videoId] = short_re.exec(text);
        result = {
            videoId: videoId,
            videoLink: videoLink,
            embedUrl: "https://www.youtube.com/embed/" + videoId
        }
    }
    else if(long_re.test(text)) {
        [videoLink, videoId] = long_re.exec(text);
        result = {
            videoId: videoId,
            videoLink: videoLink,
            embedUrl: "https://www.youtube.com/embed/" + videoId
        }
    }
    console.log("Video Extraction result: ", result);
    return result;
}

export default class Chat extends Component {

    constructor(props) {
        super(props);
        this.state = {
            messages: [],
            current: '',
        }
        this.onFormSubmit.bind(this);
    }

    handleMessage(data) {
        // NOTE: data should be an object of the form: {from: ..., message: ...}
        const new_message = {
            id: slugify(data.message) + new Date().valueOf(),  // ¯\_(ツ)_/¯
            text: data.message,
            from: data.from
        }
        const messages = _.concat(this.state.messages, [new_message]);
        this.setState({messages: messages, current: this.state.current});
        console.log('[handleMessage], this.state.current = ', this.state.current);
    }

    onFormSubmit(event) {
        event.preventDefault();
        // event.target is the form.
        // event.target[0] is the first child element (our <input>)
        const inputElement = event.target.children[0].children[0];
        const message = inputElement.value;
        console.log("[onFormSubmit] message = ", message);

        this.setState({messages: this.state.messages, current: message});

        console.log('[onFormSubmit], this.state.current = ', this.state.current);
        inputElement.value = ""; // clear the input.
    }

    renderMessageList() {
        return this.state.messages.map((msg) => {
            // A Reply is a message from the other user but not the system.
            const isReply = this.props.user.username !== msg.from && msg.from !== 'system';

            // Dont' show avatars for system messages.
            // TODO: replace this with the user's avatar.
            /*
            const avatar = (
                msg.from === "system" ? "" :
                person
            );
            */
            let avatar = '';
            if (this.props.user.avatar && !isReply && msg.from !== 'system') {
                avatar = ;
            }
            else if(msg.avatar && msg.from !== 'system') {
                avatar = ;
            }

            const chatClasses = (isReply ? 'chatBubble reply' : 'chatBubble') +
                (msg.from === 'system' ? ' notice' : '');

            // Inline links to youtube videos
            const video = extractVideo(msg.text);
            let content = msg.text;

            if(video) {
                content = (

                            {avatar}
                            <AutoLinkText text={msg.text} />

                );
            }
            else {
                content = (

                        {avatar}
                        <AutoLinkText text={msg.text} />

                );
            }

            return (

                    {content}

            );
        });
    }

    render() {
        return (

{this.renderMessageList()}

            <Websocket url={this.props.ws_url}
                       debug={true}
                       onMessage={this.handleMessage.bind(this)}
                       sendMessage={this.state.current} />
            <form onSubmit={this.onFormSubmit.bind(this)} className="chatForm">

                <input className="mdl-textfield__input"
                       type="text"
                       id="message"
                       name="message" />
                Your Message

              <button className="mdl-button mdl-js-button">Send</button>
            </form>

        );
    }
}
<|endoftext|>


<commit_before>// @ts-nocheck
module.exports = {
  // @DOM部品操作
  'DOM親要素': { type: 'const', value: '' }, // @DOMおやようそ
  'DOM部品個数': { type: 'const', value: 0 }, // @DOMせいせいこすう
  'DOM部品オプション': { type: 'const', value: {'自動改行': false} }, // @DOMぶひんおぷしょん
  'DOM親要素設定': { // @「ボタン作成」「エディタ作成」などのDOM要素を追加する対象を指定(デフォルトはdocument)して親要素のDOMオブジェクトを返す // @DOMおやようそせってい
    type: 'func',
    josi: [['に', 'へ']],
    pure: false,
    fn: function (el, sys) {
      if (typeof el === 'string') { el = document.querySelector(el) || document.getElementById(el) }
      sys.__v0['DOM親要素'] = el
      return el
    }
  },
  'DOM親部品設定': { // @「ボタン作成」「エディタ作成」などのDOM要素を追加する対象を指定。『DOM親要素設定』と同じ。// @DOMおやぶひんせってい
    type: 'func',
    josi: [['に', 'へ']],
    pure: false,
    fn: function (el, sys) {
      return sys.__exec('DOM親要素設定', [el, sys])
    }
  },
  'DOMスキン': { type: 'const', value: '' }, // @DOMすきん
  'DOMスキン辞書': { type: 'const', value: {} }, // @DOMすきんじしょ
  'DOM部品作成': { // @elmの要素を作成して『DOM親要素設定』で指定した要素に追加して、DOMオブジェクトを返す。(elmがDOM要素なら追加する) // @DOMぶひんさくせい
    type: 'func',
    josi: [['の']],
    pure: false,
    fn: function (elm, sys) {
      const parent = sys.__v0['DOM親要素']
      const btn = (typeof(elm) === 'string') ? document.createElement(elm) : elm
      btn.id = 'nadesi-dom-' + sys.__v0['DOM部品個数']
      // スキン適用
      const func = sys.__v0['DOMスキン辞書'][sys.__v0['DOMスキン']]
      if (typeof (func) === 'function') { func(elm, btn, sys) }
      // DOM追加
      parent.appendChild(btn)
      sys.__v0['DOM部品個数']++
      return btn
    }
  },
  'ボタン作成': { // @ラベルlabelを持つbutton要素を追加しDOMオブジェクトを返す // @ぼたんさくせい
    type: 'func',
    josi: [['の']],
    pure: false,
    fn: function (label, sys) {
      const btn = sys.__exec('DOM部品作成', ['button', sys])
      btn.innerHTML = label
      return btn
    }
  },
  'エディタ作成': { // @textの値を持つテキストボックス(input[type='text'])の要素を追加しDOMオブジェクトを返す // @えでぃたさくせい
    type: 'func',
    josi: [['の']],
    pure: false,
    fn: function (text, sys) {
      const inp = sys.__exec('DOM部品作成', ['input', sys])
      inp.type = 'text'
      inp.value = text
      return inp
    }
  },
  'テキストエリア作成': { // @textの値を持つtextarea要素を追加しDOMオブジェクトを返す // @てきすとえりあさくせい
    type: 'func',
    josi: [['の']],
    pure: false,
    fn: function (text, sys) {
      const te = sys.__exec('DOM部品作成', ['textarea', sys])
      te.value = text
      return te
    }
  },
  'ラベル作成': { // @textの値を持つラベル(span要素)を追加しDOMオブジェクトを返す // @らべるさくせい
    type: 'func',
    josi: [['の']],
    pure: false,
    fn: function (text, sys) {
      const lbl = sys.__exec('DOM部品作成', ['span', sys])
      lbl.innerHTML = text
      return lbl
    }
  },
  'キャンバス作成': { // @大きさ[幅, 高]のcanvas要素を追加しDOMオブジェクトを返す // @きゃんばすさくせい
    type: 'func',
    josi: [['の']],
    pure: false,
    fn: function (size, sys) {
      const cv = sys.__exec('DOM部品作成', ['canvas', sys])
      cv.width = size[0]
      cv.height = size[1]
      cv.style.width = size[0]
      cv.style.height = size[1]
      // 描画中キャンバスを移動する
      sys.__exec('描画開始', [cv, sys])
      return cv
    }
  },
  '改行作成': { // @改行(br要素)を追加しDOMオブジェクトを返す // @かいぎょうさくせい
    type: 'func',
    josi: [],
    pure: false,
    fn: function (sys) {
      const br = sys.__exec('DOM部品作成', ['br', sys])
      return br
    }
  },
  'チェックボックス作成': { // @textのラベルを持つチェックボックス(input[type='checkbox'])要素を追加しDOMオブジェクトを返す // @ちぇっくぼっくすさくせい
    type: 'func',
    josi: [['の']],
    pure: false,
    fn: function (text, sys) {
      // チェックボックスは、<input>で成り立つように構築
      const span = document.createElement('span')
      const inp = document.createElement('input')
      inp.type = 'checkbox'
      inp.id = 'nadesi-dom-' + sys.__v0['DOM部品個数']
      sys.__v0['DOM部品個数']++
      const label = document.createElement('label')
      label.innerHTML = text
      label.htmlFor = inp.id
      span.appendChild(inp)
      span.appendChild(label)
      // 親部品に追加
      sys.__exec('DOM部品作成', [span, sys])
      return inp
    }
  },
  'セレクトボックス作成': { // @配列optionsの選択肢を持つselect要素を追加しDOMオブジェクトを返す // @せれくとぼっくすさくせい
    type: 'func',
    josi: [['の']],
    pure: false,
    fn: function (options, sys) {
      const dom = document.createElement('select')
      for (let i = 0; i < options.length; i++) {
        const item = document.createElement('option')
        item.value = options[i]
        item.appendChild(document.createTextNode(options[i]))
        dom.appendChild(item)
      }
      // 親部品に追加
      const obj = sys.__exec('DOM部品作成', [dom, sys])
      return dom
    }
  },
  'DOMスキン設定': { // @「ボタン作成」「エディタ作成」などで適用するスキンを指定する(#1033) // @DOMすきんせってい
    type: 'func',
    josi: [['を', 'に', 'の']],
    pure: false,
    fn: function (skin, sys) {
      sys.__v0['DOMスキン'] = skin
    },
    return_none: true
  }
}
<commit_msg>DOM部品オプション["自動改行"]を追加。『値指定バー』『画像作成』『色選択ボックス』『日付選択ボックス作成』などDOM部品を複数追加。#1086 #1120<commit_after>// @ts-nocheck
module.exports = {
  // @DOM部品操作
  'DOM親要素': { type: 'const', value: '' }, // @DOMおやようそ
  'DOM部品個数': { type: 'const', value: 0 }, // @DOMせいせいこすう
  'DOM部品オプション': { type: 'const', value: {'自動改行': false} }, // @DOMぶひんおぷしょん
  'DOM親要素設定': { // @「ボタン作成」「エディタ作成」など『DOM部品作成』で追加する要素の親要素を指定(デフォルトはdocument)して要素を返す。 // @DOMおやようそせってい
    type: 'func',
    josi: [['に', 'へ']],
    pure: false,
    fn: function (el, sys) {
      if (typeof el === 'string') { el = document.querySelector(el) || document.getElementById(el) }
      sys.__v0['DOM親要素'] = el
      return el
    }
  },
  'DOM親部品設定': { // @ DOM部品作成でDOM要素を追加する親の対象を指定。『DOM親要素設定』と同じ。// @DOMおやぶひんせってい
    type: 'func',
    josi: [['に', 'へ']],
    pure: false,
    fn: function (el, sys) {
      return sys.__exec('DOM親要素設定', [el, sys])
    }
  },
  'DOMスキン': { type: 'const', value: '' }, // @DOMすきん
  'DOMスキン辞書': { type: 'const', value: {} }, // @DOMすきんじしょ
  'DOM部品作成': { // @elmの要素を作成して『DOM親要素設定』で指定した要素に追加して、DOMオブジェクトを返す。(elmがDOM要素なら追加する) // @DOMぶひんさくせい
    type: 'func',
    josi: [['の']],
    pure: false,
    fn: function (elm, sys) {
      const parent = sys.__v0['DOM親要素']
      const btn = (typeof(elm) === 'string') ? document.createElement(elm) : elm
      btn.id = 'nadesi-dom-' + sys.__v0['DOM部品個数']
      // スキン適用
      const func = sys.__v0['DOMスキン辞書'][sys.__v0['DOMスキン']]
      if (typeof (func) === 'function') { func(elm, btn, sys) }
      // DOM追加
      parent.appendChild(btn)
      sys.__v0['DOM部品個数']++
      // オプションを適用
      const opt = sys.__v0['DOM部品オプション']
      if (opt['自動改行']) {
        parent.appendChild(document.createElement('br'));
      }
      return btn
    }
  },
  'ボタン作成': { // @ラベルlabelを持つbutton要素を追加しDOMオブジェクトを返す // @ぼたんさくせい
    type: 'func',
    josi: [['の']],
    pure: false,
    fn: function (label, sys) {
      const btn = sys.__exec('DOM部品作成', ['button', sys])
      btn.innerHTML = label
      return btn
    }
  },
  'エディタ作成': { // @textの値を持つテキストボックス(input[type='text'])の要素を追加しDOMオブジェクトを返す // @えでぃたさくせい
    type: 'func',
    josi: [['の']],
    pure: false,
    fn: function (text, sys) {
      const inp = sys.__exec('DOM部品作成', ['input', sys])
      inp.type = 'text'
      inp.value = text
      return inp
    }
  },
  'テキストエリア作成': { // @textの値を持つtextarea要素を追加しDOMオブジェクトを返す // @てきすとえりあさくせい
    type: 'func',
    josi: [['の']],
    pure: false,
    fn: function (text, sys) {
      const te = sys.__exec('DOM部品作成', ['textarea', sys])
      te.value = text
      return te
    }
  },
  'ラベル作成': { // @textの値を持つラベル(span要素)を追加しDOMオブジェクトを返す // @らべるさくせい
    type: 'func',
    josi: [['の']],
    pure: false,
    fn: function (text, sys) {
      const lbl = sys.__exec('DOM部品作成', ['span', sys])
      lbl.innerHTML = text
      return lbl
    }
  },
  'キャンバス作成': { // @大きさ[幅, 高]のcanvas要素を追加しDOMオブジェクトを返す // @きゃんばすさくせい
    type: 'func',
    josi: [['の']],
    pure: false,
    fn: function (size, sys) {
      const cv = sys.__exec('DOM部品作成', ['canvas', sys])
      cv.width = size[0]
      cv.height = size[1]
      cv.style.width = size[0]
      cv.style.height = size[1]
      // 描画中キャンバスを移動する
      sys.__exec('描画開始', [cv, sys])
      return cv
    }
  },
  '画像作成': { // @URLを指定してimg要素を追加しDOMオブジェクトを返す // @がぞうさくせい
    type: 'func',
    josi: [['の', 'から']],
    pure: false,
    fn: function (url, sys) {
      const img = sys.__exec('DOM部品作成', ['img', sys])
      img.src = url
      return img
    }
  },
  '改行作成': { // @改行(br要素)を追加しDOMオブジェクトを返す // @かいぎょうさくせい
    type: 'func',
    josi: [],
    pure: false,
    fn: function (sys) {
      const br = sys.__exec('DOM部品作成', ['br', sys])
      return br
    }
  },
  'チェックボックス作成': { // @textのラベルを持つチェックボックス(input[type='checkbox'])要素を追加しDOMオブジェクトを返す // @ちぇっくぼっくすさくせい
    type: 'func',
    josi: [['の']],
    pure: false,
    fn: function (text, sys) {
      // チェックボックスは、<input>で成り立つように構築
      const span = document.createElement('span')
      const inp = document.createElement('input')
      inp.type = 'checkbox'
      inp.id = 'nadesi-dom-' + sys.__v0['DOM部品個数']
      sys.__v0['DOM部品個数']++
      const label = document.createElement('label')
      label.innerHTML = text
      label.htmlFor = inp.id
      span.appendChild(inp)
      span.appendChild(label)
      // 親部品に追加
      sys.__exec('DOM部品作成', [span, sys])
      return inp
    }
  },
  'セレクトボックス作成': { // @配列optionsの選択肢を持つselect要素を追加しDOMオブジェクトを返す // @せれくとぼっくすさくせい
    type: 'func',
    josi: [['の']],
    pure: false,
    fn: function (options, sys) {
      const dom = document.createElement('select')
      for (let i = 0; i < options.length; i++) {
        const item = document.createElement('option')
        item.value = options[i]
        item.appendChild(document.createTextNode(options[i]))
        dom.appendChild(item)
      }
      // 親部品に追加
      const obj = sys.__exec('DOM部品作成', [dom, sys])
      return dom
    }
  },
  '色選択ボックス作成': { // @色選択ボックス(input[type='color'])を作成しDOMオブジェクトを返す // @いろせんたくぼっくすさくせい
    type: 'func',
    josi: [],
    pure: false,
    fn: function (sys) {
      const inp = sys.__exec('DOM部品作成', ['input', sys])
      inp.type = 'color'
      return inp
    }
  },
  '日付選択ボックス作成': { // @日付選択ボックス(input[type='date'])を作成しDOMオブジェクトを返す // @ひづけせんたくぼっくすさくせい
    type: 'func',
    josi: [],
    pure: false,
    fn: function (sys) {
      const inp = sys.__exec('DOM部品作成', ['input', sys])
      inp.type = 'date'
      return inp
    }
  },
  'パスワード入力エディタ作成': { // @パスワード入力エディタ(input[type='password'])を作成しDOMオブジェクトを返す // @ぱすわーどにゅうりょくさくせい
    type: 'func',
    josi: [],
    pure: false,
    fn: function (sys) {
      const inp = sys.__exec('DOM部品作成', ['input', sys])
      inp.type = 'date'
      return inp
    }
  },
  '値指定バー作成': { // @範囲RANGE(配列で[最小,最大[,値]])を指定するバー(input[type='range'])を作成しDOMオブジェクトを返す // @ぱすわーどにゅうりょくさくせい
    type: 'func',
    josi: [['の','で']],
    pure: false,
    fn: function (range, sys) {
      if (!(range instanceof Array) || range.length < 2) {
        range = [0, 100, 50]
      }
      if (range.length <= 2) { // 3つ目を省略したとき
        range.push(Math.floor((range[1] - range[0]) / 2))
      }
      const inp = sys.__exec('DOM部品作成', ['input', sys])
      inp.type = 'range'
      inp.min = range[0]
      inp.max = range[1]
      inp.value = range[2]
      return inp
    }
  },
  '送信ボタン作成': { // @ラベルSの送信ボタン(input[type='submit'])を作成しDOMオブジェクトを返す // @そうしんぼたんさくせい
    type: 'func',
    josi: [['の']],
    pure: false,
    fn: function (label, sys) {
      const inp = sys.__exec('DOM部品作成', ['input', sys])
      inp.type = 'submit'
      inp.value = label
      return inp
    }
  },
  'フォーム作成': { // @属性OBJ{method:"GET", action:"..."}の送信フォームを作成し、DOM親部品を変更し、DOMオブジェクトを返す // @ふぉーむさくせい
    type: 'func',
    josi: [['の']],
    pure: false,
    fn: function (obj, sys) {
      const frm = sys.__exec('DOM部品作成', ['form', sys])
      for (let key in obj) {
        if (frm[key]) { frm[key] = obj[key] }
      }
      sys.__exec('DOM親要素設定', [frm, sys])
      return frm
    }
  },
  'DOMスキン設定': { // @「ボタン作成」「エディタ作成」などで適用するスキンを指定する(#1033) // @DOMすきんせってい
    type: 'func',
    josi: [['を', 'に', 'の']],
    pure: false,
    fn: function (skin, sys) {
      sys.__v0['DOMスキン'] = skin
    },
    return_none: true
  }
}
<|endoftext|>