{"id":26769906,"url":"https://github.com/bbuck/eleetscript","last_synced_at":"2025-04-15T17:11:49.658Z","repository":{"id":9673391,"uuid":"11615898","full_name":"bbuck/eleetscript","owner":"bbuck","description":"A ruby hosted scripting language, designed to add a scripting component on top or ruby applications.","archived":false,"fork":false,"pushed_at":"2019-08-19T17:08:04.000Z","size":838,"stargazers_count":10,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-15T17:11:46.445Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bbuck.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-07-23T18:31:54.000Z","updated_at":"2024-05-04T00:57:15.000Z","dependencies_parsed_at":"2022-08-18T18:31:20.880Z","dependency_job_id":null,"html_url":"https://github.com/bbuck/eleetscript","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bbuck%2Feleetscript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bbuck%2Feleetscript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bbuck%2Feleetscript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bbuck%2Feleetscript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bbuck","download_url":"https://codeload.github.com/bbuck/eleetscript/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249116245,"owners_count":21215143,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-28T22:46:22.241Z","updated_at":"2025-04-15T17:11:49.637Z","avatar_url":"https://github.com/bbuck.png","language":"Ruby","readme":"[![Gem Version](https://badge.fury.io/rb/eleetscript.svg)](http://badge.fury.io/rb/eleetscript)\n\n# Introduction\n\nEleetScript is a simple and secure scripting language designed to be hosted in\nRuby applications to add a scripting component. The desire to design a language\nfor this purpose instead of pursuing other options was to make a language with\nno default unsafe access to the system or execution of the software unless\nexplicitly given.\n\n## Status\n\nThe project is currently in an very early alpha, check below to see the status\nof the different components.\n\n- Lexer (complete (alpha))\n- Parser/Grammer (complete (alpha))\n- Runtime (complete (alpha))\n- Interpreter (complete (alpha))\n- Ruby Bridge (complete (alpha))\n- Bytecode Compiler (unstarted)\n- VM (for bytecode) (unstarted)\n\n# EleetScript Language Features\n\n## Description\n\nEleetScript was born directly from Ruby influence, and since being a language\nwritten in Ruby for Ruby (at least in it's current stage, future ports may\nhappen) it has a lot of similarities to Ruby. I've added in some minor\nenhancements that I felt rounded out the full scripting aspect of the language.\nSome of these enhancements were inspired by other languages such as CoffeeScript.\n\n## Features\n\n### Variables\n\nEleetScript supports 5 different types of variables similar to ruby.\n\n#### Constants\n\nEleetScript has constant variables which start with a capital letter and can\nonly be assigned to once. A constant can only assigned a literal value.\n\n```\nSomeConstant = 10\nCONSTANT_VALUE = \"Hello, World!\"\n```\n\n#### Globals\n\nEleetScript also supports global variables which are available at all points\nwithin a script. Globals are prefixed with a `$` character.\n\n```\n$global = List.new\n$other_global = \"Hello, World!\"\n```\n\n#### Class\n\nEleetScript provides class level variables that begin with the `@@` notation\nwhich matches the Ruby syntax; however, unlike in Ruby these variables are\ntied to a class, not a class hierarchy so they act more like static level\nvariables. This is provided becuase, unlike Ruby, EleetScript classes are not\ninstances of `Object`.\n\n```\nclass MyClass\n  @@class_variable = \"Hello, World!\"\nend\n```\n\n#### Instance\n\nEleetScript, like Ruby, also provides the same instance variable notation.\nInstance variables begin with `@` and are accessible for the instance of an\nobject.\n\n```\n@instance_var = \"Hello, World!\"\n```\n\n#### Local\n\nLast but not least are the standard local variables. Local variables are only\naccessible within the scope they are defined with the exception of Lambda's\n(which generate a \"closure\" for local variables) which will be discussed later.\n\n```\nlocal_var = \"Hello, World!\"\n```\n\n### Data Types\n\nEleetScript supports a few literal types: String, Integer, Float, Boolean and Nil.\n\n```\n\"This is a string\"\n1 # An Integer\n1.1 # A float (both Integer and Float inherit from Number)\ntrue\nyes\non  # All three of these evaluate to \"true\" and are instances of TrueClass\nfalse\nno\noff # All three of these evaluate to \"false\" and are instances of FalseClass\nnil # Instance of NilClass\n```\n\nEleetScript supports symbols with ruby syntax.\n\n```\n:some_symbol\n```\n\nEleetScript supports literal definitions for two types of objects, Lists and\nPairs. A List is the like a PHP `array()` or, for those not familiar with PHP,\nworks as both a synchronous and associative data structure. Lists can be defined\nin two different ways:\n\n```\nlist1 = List.new\nlist2 = []\n```\n\nValues can be seeded in a list literal:\n\n```\ncount = [1, 2, 3]\n```\n\nValues can be accessed and set by index:\n\n```\ncount = [1, 2, 3]\ncount[1] # =\u003e 2\ncount[1] = 4\nprintln(count) # =\u003e [1, 4, 3]\n```\n\nThe index is simply a key and any key can be used to access the array:\n\n```\njson = []\njson[\"thing\"] = \"Something Else\"\nprintln(json[\"thing\"]) # =\u003e Something Else\n```\n\nPairs can be defined as a literal as well as object. A pair is essentially a key\nvalue type of object. Since the syntatic literal definition is converted to the\nobject definition when parsed you can use dynamic values as keys as well.\n\n```\np = Pair.new(\"one\", 1)\np = \"one\" =\u003e 1\nkey = \"one\"\np = key =\u003e 1\n\np.key # =\u003e \"one\"\np.value # =\u003e 1\n```\n\nPairs provide an easy, literal, method to defining associations in a list. If\nyou mix the literal syntax:\n\n```\nlist = [1, 2, \"one\" =\u003e 1]\nlist[\"one\"] # =\u003e 1\n```\n\nYou can easily define associations.\n\n### Decisions and Loops\n\nEvery language needs a decision structure and a looping construct.\n\nEleetScript provides (as of right now) only an `if` construct for decision\nmaking. The syntax for the if statement is the same as in Ruby and just like\nRuby values are evaluated \"truthy,\" Everything but `false` (`off` and `no` included)\nand `nil` will evaluate to false.\n\n```\nif true\n  do_something\nend\n\nif one\n  do_one\nelse\n  do_two\nend\n\nif one\n  do_one\nelsif two\n  do_two\nelse\n  do_three\nend\n```\n\nEleetScript only provides one formal looping construct within the language which\nis a `while` loop. The theory was that a `while` loop can theoretically address\nany and all looping situations that may be encountered and the number of times\nthat manual loops end up written in Ruby are relatively low (in my experience).\n\nThe syntax is the same as Ruby:\n\n```\nstr = \"Hello\"\ni = 0\nwhile i \u003c str.length\n  println(str[i])\n  i += 1\nend\n```\n\n### Methods and Script Context\n\nLike Ruby, EleetScript files execute as if being executed from within a class\ndefinition. That means, for all intents and purposes, that you can picture your\nscripts as if they were written with this format:\n\n```\nclass Main \u003c Object\n  # Your script\nend\n```\n\nThis allows you to define \"global\" methods which are essentially methods defined\noutside of an explicity class context. Methods in EleetScript resemble Ruby's\n`do..end` blocks. This is the only way to define an actual method in EleetScript.\n\n```\n# Method pieces\nidentifier do |param, list|\n  body\nend\n```\n\nThe identifier is usually a simple name for the method unless you want to define\na class method in which you use a class identfier:\n\n```\n@@class_identifier do |param, title|\n  body\nend\n```\n\nParameter lists are defined in `|` operators.\n\nJust like Ruby, the last value in a method is automatically returned and things\nlike decision structures (if statements) are also considered expressions and\nreturn their last value.\n\n```\n# Some Method samples\nadd do |a, b|\n  a + b\nend\nadd(1, 2) # =\u003e 3\n\nsub do |a, b|\n  a - b\nend\nsub(3, 2) # =\u003e 1\n\nmul do |a, b|\n  a * b\nend\nmul(2, 4) # =\u003e 8\n\ndiv do |a, b|\n  a / b\nend\ndiv(6, 2) # =\u003e 3\n```\n\nMethods behave sightly different than they do in Ruby. EleetScript methods never\nrequire arguments, regardless of what parameters you specify (this is the same\nas Javascript). There is an arguments object in the scope of a method that is\na list of all the arguments passed to the function. This can provide some handy\nfeatures when realizing that arguments are essentially list definitons (more on\nthis later).\n\nMethod calls are similar to Ruby no argument calls can omit the parenthesis;\nhowever, if you pass arguments to a method you must include parenthesis. This\nhelps prevent any misunderstandings on which paramters are passed to which method\ncall (such as this example):\n\n```ruby\nan_obj.some_method one, two, other.do three, four\n```\n\nThat would be written as:\n\n```\nan_obj.some_method(one, two, other.do(three, four))\n```\n\nWhich makes the intent more clear for other programmers.\n\n#### Arguments\n\nThe `arguments` object is sometimes loved and sometimes hated in Javascript,\ndepending on the purpose it's used for, so it was not an easy choice to replicate\nthe construct with EleetScript but I felt that as a scripting language being\nable to handle arguments in such a fluid was worth the cons that would inevitably\nfollow. Due to the way the arguments is generated (it's an instance of List) it\nprovides (almost for free) the concept of \"splats\" and named paramters.\n\nTake for example the following:\n\n```\nsomething_cool do\n  if arguments[\"user\"]\n    # do something with user\n  elsif arguments[\"admin\"]\n    # do something with admin\n  end\nend\n\nsomething_cool(\"user\" =\u003e user)\nsomething_cool(\"admin\" =\u003e admin)\n```\n\n### Classes\n\nClasses are similarly defined as in Ruby, aside from the difference in method\ndefinitions. Classes can inherit a class via an extends syntax similar to Ruby\nas well. Unlike Ruby, EleetScript classes do not have a \"meta class\" or similar\nclass syntax nor the feature to modify a single instance with new methods.\n\nSimple class example:\n\n```\nclass MyClass\n  some_function do\n    println(\"Hello\")\n  end\nend\n```\n\nA more complex class example, a \"Greeter\"\n\n```\nclass Greeter\n  init do |@greeting| end\n  greet do |name|\n    println(\"%@greeting, %name!\")\n  end\nend\n```\n\nThere are a couple of undiscussed topics happening here. First is the instance\nvariable as a parameter notation. This works like it does in CoffeeScript, it\nis the equivalent of writing the function like:\n\n```\ninit do |greeting|\n  @greeting = greeting\nend\n```\n\nWhich saves time when writing initilaizers and setter functions. Also, the `init`\nfunction is the constructor for an object and will always be called when an object\nis created.\n\nFinally is the string interpolation. EleetScript only supports simple variable\ninterpolation into strings (any varaible type). To interpolate a value you begin\nwith a `%` and name the variable to be interpolated. If you wish to include a `%`\nin the string simply escape it (`\"10 \\% 10\"`). There are no plans to support any\ncomplex interpolation which forces interpolation to be logicless and clean.\n\nLike Ruby, defined classes can be reopened and added on to. These changes affect\nall instances of the class that may already exist. Using this technique as well\nas some EleetScript shorthand we can add some getters and setters to the `Greeter`\nclass.\n\n```\nclass Greeter\n  greeting= do |@greeting| end\n  greeting do @greeting end\nend\n```\n\nJust like in ruby our setter is defined as `greeting=` and can be called with some\nsome sugay simply by calling: `greeter.greeting = \"Some new Greeting\"` or, if\npreferred, `greeter.greeting=(\"Some new Greeting\")`.\n\nEven though it's fairly painless defining getters and setters in EleetScript\nit's still work and just like Ruby provides `attr_accessor` EleetScript provides\nthe `property` directive. If we rewrite the Greeter exampe (getter and setter\nincluded) we get:\n\n```\nclass Greeter\n  property greeting\n  init do |@greeting| end\n  greet do |name|\n    println(\"%@greeting, %name!\")\n  end\nend\n```\n\nThe `property` directive will create a getter and setter for the named value\ngiven. Notice the name is not a string or symbol (which don't currently exist\nin EleetScript), this is how property names are defined, in a space seperated list\nfollwing a property directive.\n\n```\nclass MyClass\n  property one two three\nend\n```\n\nInheritance works much like it does in Ruby, the inheritance directive is a `\u003c`\nfollowed by the name of the class to inherit from.\n\n```\nclass A\nend\n\nclass B \u003c A\nend\n```\n\nYou can call the super implementaiton for a method with the `super` keyword.\nUnlike in Ruby, however, you do have to explicitly pass the expected parameters\nthrough `super`.\n\n```\nclass Greeter\n  init do\n    @@greeting = \"Hello\"\n  end\n\n  greet do |name|\n    greeting = @@greeting\n    \"%greeting, %name!\"\n  end\nend\n\nclass SPGreeter \u003c Greeter\n  init do\n    @@greeting = \"Hola\"\n  end\n\n  greet do |name|\n    \"¡\" + super(name)\n  end\nend\n```\n\nCalling `Greeter.new.greet('World')` should return `\"Hello, World!\"` while\n`SPGreeter.new.greet('Mundo')` should return `\"¡Hola, Mundo!\"`, having\npre-pended the inverted exclamation point, and otherwise shared the same\nimplemenation as the parent\n\n## Namespaces\n\nA Namespace is essentially a means for seperating code. This is mostly an\nadvanced language feature that won't find much use without the ability to import\nfiles (which does not currenlty exist). Although the feature is in place and\nusable.\n\n```\nnamespace Mathematics\n  class Algebra\n  end\n\n  class Calculus\n  end\n\n  class LinearAlgebra\n  end\nend\n```\n\nNamespaces are similar to Ruby modules and accessing their contents is the same:\n\n```\nMathematics::LinearAlgebra.new\n```\n\nUnlike Ruby modules, they're nothing more than ways to seperate code.\n\n## Lambdas And LeetSauce\n\nLambdas are to EleetScript as a Proc/Lambda is to Ruby. Lambdas behave similar\nto methods (and behind the scenes they are simply methods with some scoping\nmagic) except they can be stored in variables and invoked when needed. They also\nprovide a basic closure wrapping for local variables defined in the same scope\nthe lambda is defined.\n\nThe goal of EleetScript was to try and provide a \"one way to do it\" methodology\non top of Ruby's \"Do it however you want\" method. So for example in Ruby you\ndefine a method in one of two ways:\n\n```ruby\ndef method_name(args)\n  # body\nend\n\ndefine_method :method_name do |args|\n  # body\nend\n```\n\nNow, granted that almsot always you should use the first method apart from dynamic\nmethod generation for DSL's and other Meta programming constructs but you can\nalso define Procs/Lambdas in multiple ways:\n\n```ruby\nlambda { lambda_body }\n-\u003e { lambda_body }\nProc.new do\n  proc_body\nend\nProc.new { proc_body }\n```\n\nIn EleetScript there is one syntax for defining a method (as shown before) and\none method for defining a lambda.\n\n```\nlambda_add = -\u003e { |a, b| a + b }\n\n# OR\n\nlambda_add = -\u003e { |a, b|\n  a + b\n}\n\nlambda_add.call(1, 2) # =\u003e 3\n```\n\nMethods are designed to try and integrate lambdas as final parameters just as\nRuby methods do with the way blocks are given to methods. This allows for some\ninterator type constructs used commonly in Ruby to translate directly to\nEleetScript.\n\n```\n# Times\n10.times -\u003e { |i|\n  # do something\n}\n\n[1, 2, 3].each -\u003e { |item, index|\n  # do something\n}\n\n[1, 2, 3].map -\u003e { |item| item * 2 }\n[1, 2, 3].inject(0) -\u003e { |sum, item| sum + item }\n# The above has already been defined as\n[1, 2, 3].sum\n```\n\nIf you want to define a method that can take a lambda, that's easy as well. They\nare simply instances of the Lambda class and be any argument in the list, or if\ndefined trailing a function call will be the last value in the arguments List as\nwell as specially referenced by the `lamdba` local variable. There is also a helper\nvalue that you can use to determine if a lamdba was given to a method: `lambda?`.\n\n```\nclass MyClass\n  my_lambda_method do\n    if lambda?\n      lambda.call(thing)\n    end\n  end\nend\n```\n\n## Regular Expressions\n\nThanks to the Ruby backing EleetScript has full access to Ruby's unique \"irRegular\nExpression\" engine. You can access Regular Expressions in the language with a\nspecial literal syntax of by creating one with via the `Regex` class.\n\n```\n# Literal\nname_rx = r\"my name is (.+)\"i\n\n# Class Based\nname_rx = Regex.new(\"my name is (.+)\", \"i\")\n```\n\nIf you wish to test a string against a regular expression you will find that\nEleetScript supports the `=~` operator, which you might find more forgiving\nthan Rubys (`String =~ Regexp` in Ruby, either way in EleetScript).\n\n```\nrx = r\"my name is (.+)\"i\nstr = \"My name is Brandon\"\n\nif str =~ rx # or str.match?(rx)\n  matches = str.match(rx)\n  # matches is a list of all matches, match[0] is the full match and indexes/keys\n  # are matched groups - in this case matches[1] is equal to group 1.\n  name = matches[1]\n  println(\"Your name is %name\")\nend\n\nrx = r\"my name is (?\u003cname\u003e.+)\"i\nif str =~ rx\n  matches = str.match(rx)\n  # Named groups are accessed by their names\n  name = matches[\"name\"]\n  println(\"Your name is %name\")\nend\n```\n\nThe flags you can apply to a regular expression are similar to Ruby as well.\nThere is a multiline flag (`m`), ignore case flag (`i`) and global flag (`g`).\nThe only one not present in Ruby is the global flag which changes the scope\nof the regular expression. In Ruby that is done depending on the method used with\nthe regular expression.\n\n```\n\"ababab\".replace(r\"a\", \"c\") # =\u003e \"cbabab\"\n\"ababab\".replace(r\"a\"g, \"c\") # =\u003e \"cbcbcb\"A\n```\n\n## Reasoning for creating a new layer\n\nThere were three main driving factors into the development of EleetScript:\n\n1. Eliminate a lot of complexity that can accompany Ruby programs (complexity in\nterms of new developers). This would, theoretically, make EleetScript easier to\npick up for entry level programmers or non-programmers. This one done by forcing\ncertain redability contstructs and trimming out certains ways to do things.\n1. Make a default secure runtime. The EleetScript Engine has no access to the\nfile system or process so malicious developers can't perform any bad actions\nlike this. The way the Engine is implemented you can easily add in access to\nthese features (like in the basic Engine introduction).\n1. Errorless. This is something to take with a grain of salt. Originally I had\nplanned any error you would normally see happen in a language (like Ruby) such\nas Undefined method or Undefined variable should be silently ignored and simply\ngiven a value. This, obviously, was a really poor choice but I wanted to continue\nwith the premise that the scripts wouldn't \"error out\" if issues were encountered\nand so there is a global \"Errors\" List where messages are placed when an error\noccurs. This list can be checked to determine if certain portions of the script\nare throwing errors and can be cleared before a new section to test for errors\nthere.\n\n# Ruby Bridge (Engine)\n\nWhat's a scripting engine without a language integration feature?\n\nThe Engine is written to try and provide near seamless interaction with the\nscripting engine. The engine provides an interface for manually executing\ncode, calling fuctions, setting values or fetching values from withing the\nEleetScript runtime instance.\n\nThere are two types of Engines that you can choose from when integrating with\nEleetScript. The one you choose is dependant on how you plan on using/access the\nscript portions of your code. You can use the `SharedEngine` which uses a shared\nmemory between all instances (every instance of `SharedEngine` uses the same\ncore `Memory` object) and creates a unique context per instance to keep conflicts\nfrom arising between different scripts and `SharedEngine` instances. The\n`StandaloneEngine` creates a `Memory` object per instnace guaranteeing a completely\nstandalone context per instance for scripts.\n\nIf you only plan to use one engine in your program then the choice between shared\nor standalone will, ultimately, make no difference. In large applications where\nseveral different engines (large number of simulatneous scripts) need to be\nmanaged then the `SharedEngine` may be more efficient due to no duplication of\nEleetScript's core.\n\nHere is an example (with comments) of doing certain things with the engine.\n\n```ruby\nrequire \"eleetscript\"\n\nengine = ES::SharedEngine.new\n\nnew_method = \u003c\u003c-ES\nreturn_nil do\n  nil\nend\nES\n\nengine.execute(new_method) # runs the code\nes_nil = engine.call(:new_method)\n\nes_nil == nil # =\u003e The Engine converts Strings, Integers, Floats, true, false\n# and nil to their direct ruby equivalents, no wrapper here!\n\nadd_method = \u003c\u003c-ES\nadd do |a, b|\n  a + b\nend\nES\n\nengine.execute(add_method)\nten = engine.call(:add, 6, 4)\nten # =\u003e 10\n\nESList = engine[\"List\"] # fetch the value of \"List\" from the runtime\n# ESList is now a EleetToRubyWrapper that allows you to interact with it as if\n# it had been defined in Ruby\n\nlist = ESList.new # Creates a new list, again EleetToRubyWrapper\nlist \u003c \"String\" # The '\u003c' method in EleetScript is shorthand for push and similar to \u003c\u003c in ruby\nlist[0] # =\u003e \"String\"\nlist[\"Other Value\"] = 1\nlist[\"Other Value\"] # =\u003e 1\n\n# If you want your script to access the file system, provide the ruby File class\nengine[\"File\"] = File\n\nscript = \u003c\u003c-ES\nstr = File.open(\"some_file.txt\")\nprintln(str)\nES\n\nengine.execute(script)\n```\n\nThere may still come a need to protect certain aspects of your class from\nscripts in EleetScript. It's default security mechanisms are in place to\nprotect the filesystem and process; however, you may have sensitive data, such\nas Database objects that you don't want modified from within the EleetScript\nruntime. The EleetScrpt Engine provides two methods for locking access. The\nfirst is more secure and reliable:\n\nTo whitelist methods add an `eleetscript_allow_methods` function to the proper\nscope of the object (class or instance or both) that returns an array of\nmethods names that EleetScript has access to. This array must be an\narray of symbols. This function is a **whitelist**.\n\n```ruby\nclass Test\n  def one\n    1\n  end\n  def two\n    2\n  end\n  def eleetscript_allow_methods\n    [:one]\n  end\nend\n\nengine = ES::SharedEngine.new\nengine[\"test\"] = Test.new\n\nengine.evaluate(\"a.one\") # =\u003e 1\nengine.evalaute(\"a.two\") # =\u003e nil\nengine[\"Errors\"].last # =\u003e Attempt to call locked method \"two\" failed.\n\n# This method is secure against generating new instances from within the\n# langauge\n\nengine.evaluate(\"b = a.class_ref.new\")\nengine.evaluate(\"b.two\") # =\u003e nil\nengine[\"Errors\"].last # =\u003e Attempt to call locked method \"two\" failed.\n```\n\nAdd an `eleetscript_lock_methods` function to the proper scope of the object\n(class or instance or both) that returns an array of methods names that\nEleetScript does not have access to. This array must be an array of symbols.\nThis function is a **blacklist**.\n\n```ruby\nclass Test\n  def one\n    1\n  end\n  def two\n    2\n  end\n  def eleetscript_lock_methods\n    [:two]\n  end\nend\n\nengine = ES::SharedEngine.new\nengine[\"test\"] = Test.new\n\nengine.evaluate(\"a.one\") # =\u003e 1\nengine.evalaute(\"a.two\") # =\u003e nil\nengine[\"Errors\"].last # =\u003e Attempt to call locked method \"two\" failed.\n\n# This method is secure against generating new instances from within the\n# langauge\n\nengine.evaluate(\"b = a.class_ref.new\")\nengine.evaluate(\"b.two\") # =\u003e nil\nengine[\"Errors\"].last # =\u003e Attempt to call locked method \"two\" failed.\n```\n\nYou can use two special cass modifiers when using the method definition approach:\nIf you wisth to whitelist/blacklist all methods then use `:all`, if you wish to\nwhitelist/blacklist no methods use `:none`. It's important to understand that\nallowing `:all` or locking `:none` is the same as not defining these methods\nwhile allowing `:none` and locking `:all` achieve the same goal.\n\nOnly the whitelist (`eleetscript_allow_methods`) or the blacklist\n(`eleetscript_lock_methods`) will be used, allow has precedence.\n\nThe other method is to use the Engine's `set` method instead of `[]` and\nspecifiying what methods to lock as either a symbol or an array of symbols.\nYou can manually lock methods via `:lock` or allow method with `:allow`. **NOTE**:\nUsing these manual methods overrides the usage of the class methods, meaning\nthe two cannot be used in unison.\n\n```ruby\nclass Test\n  def one\n    1\n  end\n  def two\n    2\n  end\nend\n\nengine = ES::SharedEngine.new\nengine.set(\"a\", Test.new, lock: :two)\nengine.evaluate(\"a.one\") # =\u003e 1\nengine.evaluate(\"b.one\") # =\u003e nil\nengine[\"Errors\"].last # =\u003e Attempt to call locked method \"two\" failed.\n\n# However this can be circumvented by a smarter scripter\n\nengine.evaluate(\"b = a.class_ref.new\")\nengine.evaluate(\"b.two\") =\u003e 2\n```\n\nUnless you have reason to, you should always use the first method for defining\nmethod locks.\n\nThe API is the same for both engine types; however, the `SharedEngine` offers\none feature unique to it. This feature, `SharedEngine#reset` allows you to start\nwith a new context (clearing all changes made to the local context of the instance).\n**NOTE**: If you modify any core objects the modification will reflect across all\ninstances of `SharedEngine`.\n\n# Name\n\nI thought I should include this little blurb about the name. I wanted to make\nit clear that this language was not named **Eleet**Script to signify that it's\nbetter than any other language. It was named as such becuase when I first begin\nfantasizing about what the language should look like and do and what language it\nshould run on initially I had registered a company name called \"Eleet Software\nDevelopers, L.L.C.\" which got it's name becuase I thought it was funny to play\nwith the elitist attitude the a lot of people have and of course imply that we\ndid good work.\n\nLong story short, the name evolved from that and lack of a more creative name\nto come to me before I released it.\n\n# License\n\n[MIT](http://opensource.org/licenses/MIT)\n\nCopyright (c) 2013 Brandon Buck\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbbuck%2Feleetscript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbbuck%2Feleetscript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbbuck%2Feleetscript/lists"}