Skip to content

fcostin/abfc_hs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

abfc_hs work-in-progress

Port of abfc macro-language-to-brainfuck compiler to Haskell.

This includes its own Parsec parser for the macro language.

STATUS

Successfully compiles self_hosting_bf_compiler_x86_64_test.py. The resulting brainfuck program functions correctly when used in abfc's pipeline.

COMPONENTS

  • main is the main definition for the command-line program
  • Parser is the parsec macro parser
  • Macros is the datatype for the compiler's internal macro representation
  • Compile performs macro-level transformations : rewriting local statements, if blocks, while blocks, and inlining all function calls, starting from the body of the main macro. This results in one huge list of simplified statements.
  • Eval evaluates the list of simplified statements generated by Compile. It deals mainly with managing the environments (i.e. scopes) of the program. It handles local variable allocation and release when scopes are entered and exited, and resolves lookups of variable values by name (to either allocated memory addresses or constant values). The only thing Eval doesn't do is handle built-in calls - the evaluation of built in calls is delegated to BuiltInDispatch.
  • Env is a nested environment data structure used by Eval to manage variable scopes and lookup.
  • Allocator is the data structure used to track the locations of allocated addresses. It is used by both Eval and MachineCodegen to allocate local variables to the stack.
  • ResolvedArgs is a simple data type used by Eval to pass resolved built-in function call arguments to BuiltInDispatch.
  • BuiltInDispatch defines the list of built-in function calls that are recognised. These calls are dispatched to functions in MachineCodegen.
  • MachineCodegen defines the built-in functions. These functions are basic operations such as MOVE, LOGICAL_NOT, READ, BEGIN_LOOP that take a small number of arguments (typically stack offsets for local variable addresses, but sometimes int or string constants) and map them to actions. Actions update the code generation state - this is a 3-tuple of type (String, Machine, Allocator), where the first element tracks the generated opcodes, the second element tracks the state of the simple brainfuck stack machine (i.e. the stack and data pointers, and the stack of loop addresses), while the third element is the Allocator in charge of assigning and tracking stack addresses of local variables. The Allocator state needs to be tracked because many of the built-in functions require allocation of local variables for temporaries. The built-in functions themselves are defined as the composition of lists of basic actions that act upon the code generation state. This maps quite naturally over to the semantics of the stack-machine and is relatively boilerplate-free.
  • Machine defines the data type for the brainfuck stack-machine.

TODO

  • learn how to eliminate boilerplate for "stateful" bits of computation in Machine, Allocator, Env, Eval, etc. State monad?
  • refine the syntax accepted by the parser to be nicer - e.g. not an ugly python dsl

About

port of abfc to haskell

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published