Skip to content
/ fofi Public

functionally-pure compiler for the π’‡π’π’‡π’Š language, implemented in Haskell :)

Notifications You must be signed in to change notification settings

herniqeu/fofi

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

7 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

FOFI Compiler

FOFI originated as a university project in Brazil, designed to help occupational therapists create thematic games for children on the autism spectrum. To learn more (in Portuguese), check out the local coverage: here.

A high-performance, functionally-pure compiler for the FOFI language, implemented in Haskell. FOFI (Framework Orientado para Facilitação Inclusiva) is a simple, statically-typed programming language inspired by both imperative and functional paradigms. Our compiler is built with modular design techniques, providing a clean architecture for lexical analysis, parsing, semantic analysis, and code generation.


Table of Contents

  1. Introduction
  2. Features
  3. Installation
  4. Using the Compiler
  5. Code Overview
  6. Examples
  7. Contributing
  8. License

Introduction

FOFI is designed to be easy to learn and powerful enough to demonstrate key concepts of compiler design. It achieves: β€’ Functional-purity: Emphasizing immutable data structures and declarative design.
β€’ High-level abstractions: Leveraging Haskell's monadic parser combinators and lazy evaluation.
β€’ Readable syntax: Drawing ideas from both imperative and functional styles, making it easy to transition from other languages.

See the FOFI language documentation for more details about the syntax, data types, control structures, and built-in functions.


Features

β€’ Lexical Analysis using deterministic finite automata (DFA).
β€’ Recursive Descent Parsing with monadic combinators.
β€’ Polymorphic Type Inference and advanced semantic checks.
β€’ Intermediate Representation in continuation-passing style (CPS).
β€’ Optimized JavaScript Code Generation.
β€’ Cross-platform: The compiler is written in Haskell using GHC, so it runs on most systems.


Installation

To build and install the compiler, make sure you have GHC (Glasgow Haskell Compiler) and Cabal installed.
Then, from the repository root, run:

cabal update
cabal install --only-dependencies
cabal build

This will produce the binary (called "fofi-compiler" by default) in one of Cabal's build directories.


Using the Compiler

Once compiled, run:

./dist/newstyle/build/.../fofi-compiler <input-file>

The compiler will:

  1. Lex and parse the input FOFI file.
  2. Perform semantic checks (type checking, variable declarations, etc.).
  3. Generate the corresponding JavaScript code (saving it in .js).

A typical command might look like:

fofi-compiler my_program.fofi

If compilation succeeds, you'll see:

Compilation successful!

Check out the newly generated "my_program.fofi.js" file in the same directory.


Code Overview

This repository is organized into key modules, each handling a major phase of compilation. Below are brief overviews of some files and a sample of how they work.

1. Main Entry Point

The compiler's top-level behavior is defined in src/Main.hs. It reads command-line arguments, calls into the different phases, and writes the final JavaScript output.

module Main where

import System.Environment (getArgs)
import Lexer (tokenize)
import Parser (parse)
import SemanticAnalyzer (analyze)
import CodeGenerator (generate)

main :: IO ()
main = do
    args <- getArgs
    case args of
        [inputFile] -> do
            contents <- readFile inputFile
            let tokens = tokenize contents
            case parse tokens of
                Left error -> putStrLn $ "Parse error: " ++ error
                Right ast -> do
                    case analyze ast of
                        Left error -> putStrLn $ "Semantic error: " ++ error
                        Right _ -> do
                            let code = generate ast
                            writeFile (inputFile ++ ".js") code
                            putStrLn "Compilation successful!"
        _ -> putStrLn "Usage: fofi-compiler <input-file>"

2. Lexer

Lexer.hs transforms raw text into tokens (e.g., identifiers, types, operators):

module Lexer where

import Data.Char (isAlpha, isAlphaNum, isDigit, toLower)

data Token = Token
    { tokenType :: String
    , tokenValue :: String
    , tokenLine :: Int
    } deriving (Show, Eq)

-- Core lexer function 
tokenize :: String -> [Token]
tokenize input = ...

3. Parser

Parser.hs converts tokens into an Abstract Syntax Tree (AST). We use a recursive descent approach. Once the AST is built, we can do further checks or transformations:

module Parser where

import Lexer (Token(..))

data AST = ...
-- This data type encapsulates the entire structure of the program.
 
parse :: [Token] -> Either String AST
parse tokens = ...

4. Semantic Analysis

SemanticAnalyzer.hs checks for type correctness, variable declarations, etc. It uses a symbol table to ensure everything is well-typed:

module SemanticAnalyzer where

import qualified Data.Map as Map
import Parser (AST(..), Expression(..))

analyze :: AST -> Either String ()
analyze (Program _ varDecls stmts) = ...

5. Code Generation

CodeGenerator.hs traverses the validated AST and emits JavaScript code:

module CodeGenerator where

import Parser (AST(..), Expression(..))

generate :: AST -> String
generate (Program desc varDecls stmts) = ...

Examples

Below is a minimal "Hello, FOFI!" example. For a more in-depth guide, see the FOFI Language Documentation.

Create a file named hello.fofi:

programa
"This is a simple FOFI program"

var
texto message;

{
    message : "Hello, FOFI!";
    mostrar(message);
}

Compile it:

fofi-compiler hello.fofi

You'll get hello.fofi.js. Run it with Node.js (or any JavaScript runtime):

node hello.fofi.js

Expected output:

Hello, FOFI!

For additional examples, including control structures, function usage, and advanced graphics/animation, check out docs/README.md.


Contributing

We welcome contributions! If you'd like to propose a feature or fix a bug:

  1. Fork the repository and make your changes in a new branch.
  2. Create a Pull Request describing your changes.
  3. Ensure your code passes any relevant tests.

Also, please open an issue if you find any bugs or have feature requests. See CONTRIBUTING.md for details.


About

functionally-pure compiler for the π’‡π’π’‡π’Š language, implemented in Haskell :)

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published