Skip to content

Commit 8f20daa

Browse files
Add support for the Fennel programming language
1 parent 3025a53 commit 8f20daa

File tree

5 files changed

+116
-0
lines changed

5 files changed

+116
-0
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"""
2+
This script translates problems from the OpenAI HumanEval dataset into Fennel.
3+
4+
- Home: https://fennel-lang.org/
5+
- Compiler: https://git.sr.ht/~technomancy/fennel
6+
- Test library: https://git.sr.ht/~technomancy/faith
7+
"""
8+
9+
import ast
10+
from typing import List
11+
12+
13+
class Translator:
14+
15+
USub = "-"
16+
17+
stop = ["\n(fn", "\n;", "\n("]
18+
19+
def file_ext(self):
20+
return "fnl"
21+
22+
def translate_prompt(
23+
self, name: str, args: List[ast.arg], _returns, description: str
24+
) -> str:
25+
fnl_args = " ".join([arg.arg for arg in args])
26+
fnl_description = description.replace('"', '\\"')
27+
self.entry_point = name
28+
return f'(fn {name} [{fnl_args}]\n"{fnl_description}"\n'
29+
30+
def test_suite_prefix_lines(self, entry_point) -> List[str]:
31+
return [
32+
"(local faith (require :faith))",
33+
f"(local candidate {entry_point})",
34+
"(fn test-human-eval []",
35+
]
36+
37+
def test_suite_suffix_lines(self) -> List[str]:
38+
return [")", "{: test-human-eval}"]
39+
40+
def deep_equality(self, left: str, right: str) -> str:
41+
return f" (faith.= {right} {left})" # Expected on the left.
42+
43+
def gen_literal(self, c: bool | str | int | float):
44+
if type(c) is bool:
45+
return "true" if c else "false"
46+
elif type(c) is str:
47+
return f'"{c}"'
48+
elif c is None:
49+
return "nil"
50+
return repr(c)
51+
52+
def gen_var(self, variable: str) -> str:
53+
return variable
54+
55+
def gen_list(self, list: List[str]) -> str:
56+
return "[" + " ".join(list) + "]"
57+
58+
def gen_tuple(self, tuple: List[str]) -> str:
59+
return "[" + " ".join(tuple) + "]"
60+
61+
def gen_dict(self, keys: List[str], values: List[str]) -> str:
62+
pairs = " ".join(f"{k} {v}" for k, v in zip(keys, values))
63+
return "{" + pairs + "}"
64+
65+
def gen_call(self, func: str, args: List[str]) -> str:
66+
return "(" + func + " " + " ".join(args) + ")"

dataset_builder/terms.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ Matlab,m,array,array,array,dictionary,<missing>,true,false
2626
Haskell,hs,list,list,tuple,association list,Nothing,True,False
2727
Clojure,clj,vector,list,vector,map,nil,true,false
2828
Dart,dart,list,list,record,map,null,true,false
29+
Fennel,fnl,table,table,table,table,nil,true,false

evaluation/Dockerfile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,14 @@ RUN apt-get update -yqq && apt-get install -yqq dart
106106
# Lean
107107
# RUN wget https://github.com/leanprover/lean4/releases/download/v4.6.0-rc1/lean-4.6.0-rc1-linux.zip -O /tmp/lean.zip && unzip /tmp/lean.zip -d /root/lean/ && ln -s /root/lean/bin/lean /bin/lean
108108

109+
# Fennel
110+
# TODO Once on Ubuntu 25.10+, replace with `apt install -y fennel'.
111+
RUN curl -L -O https://fennel-lang.org/downloads/fennel-1.6.1
112+
RUN curl -L -O https://git.sr.ht/~technomancy/faith/blob/main/faith.fnl
113+
RUN chmod +x fennel-1.6.1
114+
RUN ln -s /fennel-1.6.1 /bin/fennel
115+
ENV FENNEL_PATH=/?.fnl
116+
109117
# install numpy for humanevalplus
110118
RUN python3 -m pip install numpy
111119

evaluation/src/containerized_eval.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import eval_v
3030
import eval_lean
3131
import eval_dart
32+
import eval_fnl
3233
import tempfile
3334

3435

@@ -65,6 +66,7 @@
6566
"coq": (eval_v.eval_script, ".v"),
6667
"lean": (eval_lean.eval_script, ".lean"),
6768
"dart": (eval_dart.eval_script, ".dart"),
69+
"fnl": (eval_fnl.eval_script, ".fnl")
6870
}
6971

7072
def eval_string_script(language, program):

evaluation/src/eval_fnl.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""
2+
Evaluates a generated Fennel program (.fnl).
3+
"""
4+
import os
5+
from pathlib import Path
6+
from safe_subprocess import run
7+
from libeval import run_without_exn
8+
9+
def eval_script(path: Path):
10+
11+
module_dir = path.parent
12+
module = path.stem
13+
14+
old_path = os.environ["FENNEL_PATH"]
15+
new_path = f'{old_path};{module_dir}/?.fnl'
16+
17+
args = ["fennel", "/faith.fnl", "--tests", module]
18+
env = {'FENNEL_PATH': new_path}
19+
20+
result = run(args, env = env)
21+
22+
if result.timeout:
23+
status = "Timeout"
24+
elif result.exit_code != 0:
25+
status = "Exception"
26+
elif "\n1 passed, 0 failed, 0 error(s), 0 skipped\n" in result.stdout:
27+
status = "OK"
28+
else: # test failure
29+
status = "Exception"
30+
31+
return {
32+
"status": status,
33+
"exit_code": result.exit_code,
34+
"stdout": result.stdout,
35+
"stderr": result.stderr,
36+
}
37+
38+
if __name__ == "__main__":
39+
main()

0 commit comments

Comments
 (0)