Created
November 25, 2025 10:01
-
-
Save DataKinds/46b9cc68b3ded20bc199c864df3f867a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require 'pry' | |
| # stack ops | |
| def pop stack | |
| stack.pop | |
| end | |
| def push(stack, x) | |
| stack.push x | |
| end | |
| def call(stack, fn_sym) | |
| fn = method(fn_sym) | |
| n = fn.arity.abs - 1 | |
| puts "CALLING #{fn} ON STACK #{stack} POPPING #{n}" if $DEBUG | |
| xs = (1..n).map do pop stack end | |
| fn[stack, *n] | |
| end | |
| # parser | |
| def lex input | |
| input.split(/\s+/) | |
| end | |
| class Quote | |
| attr_accessor :words | |
| def initialize(words) | |
| @words = words | |
| end | |
| def inspect | |
| "[ #{@words.map(&:inspect).join" "} ]" | |
| end | |
| end | |
| class Comptime | |
| attr_accessor :words | |
| def initialize(words) | |
| @words = words | |
| end | |
| def inspect | |
| "[ #{@words.map(&:inspect).join" "} ]" | |
| end | |
| end | |
| def parse words | |
| out = [] | |
| idx = 0 | |
| while idx < words.length | |
| word = words[idx] | |
| case word | |
| when '[' # parse quotes | |
| starting = idx+1 | |
| depth = 1 | |
| while depth > 0 | |
| raise "Unbalanced quote brackets" if idx > words.length | |
| peek = words[idx += 1] | |
| depth -= 1 if peek == ']' | |
| depth += 1 if peek == '[' | |
| end | |
| ending = idx-1 | |
| out << Quote.new(parse words[starting..ending]) | |
| when '{' # parse comptime brackets | |
| starting = idx+1 | |
| depth = 1 | |
| while depth > 0 | |
| raise "Unbalanced comptime brackets" if idx > words.length | |
| peek = words[idx += 1] | |
| depth -= 1 if peek == '}' | |
| depth += 1 if peek == '{' | |
| end | |
| ending = idx-1 | |
| out << Comptime.new(parse words[starting..ending]) | |
| else | |
| out << word | |
| end | |
| idx += 1 | |
| end | |
| out | |
| end | |
| # runtime words | |
| def hello(stack, person) | |
| puts "hello, #{person}!" | |
| end | |
| class SumType | |
| def initialize(*variants) | |
| @variants = variants.flatten | |
| end | |
| def +(other_type) | |
| SumType.new(@variants, other_type) | |
| end | |
| end | |
| class ProductType | |
| def initialize(*fields) | |
| @fields = fields.flatten | |
| end | |
| def *(other_type) | |
| ProductType.new(@fields, other_type) | |
| end | |
| end | |
| # runtime | |
| def register(names, fn_sym) | |
| names[fn_sym.name] = fn_sym | |
| end | |
| def run(ast, is_comptime, stack = [], names = {}) | |
| register(names, :hello) | |
| ast.each do |term| | |
| if is_comptime | |
| case term | |
| when Comptime | |
| # TODO | |
| end | |
| else | |
| case term | |
| when String # the term is a bare function to call | |
| fn_sym = names[term] | |
| raise "got unrecognized name #{term}" if fn_sym.nil? | |
| call(stack, fn_sym) | |
| when Quote | |
| push(stack, term) | |
| when Comptime | |
| else | |
| push term | |
| end | |
| end | |
| end | |
| return stack, names | |
| end | |
| def full(input) | |
| ast = parse(lex(input)) | |
| stack, comptime_names = run(ast, true) | |
| run(ast, false, names = comptime_names) | |
| end | |
| puts parse(lex "hello [ wrld [ ] ]") | |
| puts run(parse(lex "hello [ wrld [ ] ]"), false) | |
| # puts full("hello [ wrld [ ] ]") | |
| pry |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment