Skip to content

Commit

Permalink
test JS compilation
Browse files Browse the repository at this point in the history
  • Loading branch information
mariusandra committed Nov 12, 2024
1 parent 8342c15 commit 31c0f77
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 64 deletions.
3 changes: 3 additions & 0 deletions bin/hoge
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ set -e

if [[ "$@" == *".hog"* ]]; then
exec python3 -m posthog.hogql.cli --compile "$@"
elif [[ "$@" == *".js"* ]]; then
exec python3 -m posthog.hogql.cli --compile "$@"
else
echo "$0 - the Hog compilër! 🦔+🕶️= Hoge"
echo ""
echo "Usage: bin/hoge <file.hog> [output.hoge] compile .hog into .hoge"
echo " bin/hoge <file.hog> <output.js> compile .hog into .js"
echo " bin/hog <file.hog> run .hog source code"
echo " bin/hog <file.hoge> run compiled .hoge bytecode"
exit 1
Expand Down
2 changes: 1 addition & 1 deletion hogvm/stl/compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import json

from posthog.hogql import ast
from posthog.hogql.bytecode import create_bytecode, parse_program
from posthog.hogql.compiler.bytecode import create_bytecode, parse_program

source = "hogvm/stl/src/*.hog"
target_ts = "hogvm/typescript/src/stl/bytecode.ts"
Expand Down
18 changes: 15 additions & 3 deletions hogvm/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,23 @@ for file in hogvm/__tests__/*.hog; do
./bin/hoge $file $basename.hoge
./bin/hog --nodejs $basename.hoge > $basename.stdout.nodejs
./bin/hog --python $basename.hoge > $basename.stdout.python

set +e
./bin/hoge $file $basename.js
node $basename.js > $basename.stdout.compiledjs 2>&1
set -e

set +e
diff $basename.stdout.nodejs $basename.stdout.python
diff $basename.stdout.nodejs $basename.stdout.compiledjs
if [ $? -eq 0 ]; then
mv $basename.stdout.nodejs $basename.stdout
rm $basename.stdout.python
diff $basename.stdout.nodejs $basename.stdout.python
if [ $? -eq 0 ]; then
mv $basename.stdout.nodejs $basename.stdout
rm $basename.stdout.python
rm $basename.stdout.compiledjs
else
echo "Test failed"
fi
else
echo "Test failed"
fi
Expand Down
76 changes: 42 additions & 34 deletions posthog/hogql/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from hogvm.python.execute import execute_bytecode
from posthog.hogql.compiler.bytecode import create_bytecode, parse_program
from posthog.hogql.compiler.javascript import to_js_program

modifiers = [arg for arg in sys.argv if arg.startswith("-")]
args = [arg for arg in sys.argv if arg != "" and not arg.startswith("-")]
Expand All @@ -14,46 +15,53 @@
with open(filename) as file:
code = file.read()

if filename.endswith(".hog"):
bytecode = create_bytecode(parse_program(code)).bytecode
else:
bytecode = json.loads(code)
if "--compile" in modifiers and len(args) == 3 and args[2].endswith(".js"):
target = args[2]
js_program = to_js_program(code)
with open(target, "w") as file:
file.write(js_program + "\n")

if "--run" in modifiers:
if len(args) != 2:
raise ValueError("Must specify exactly one filename")
else:
if filename.endswith(".hog"):
bytecode = create_bytecode(parse_program(code)).bytecode
else:
bytecode = json.loads(code)

response = execute_bytecode(bytecode, globals=None, timeout=5, team=None, debug="--debug" in modifiers)
for line in response.stdout:
print(line) # noqa: T201
if "--run" in modifiers:
if len(args) != 2:
raise ValueError("Must specify exactly one filename")

elif "--out" in modifiers:
if len(args) != 2:
raise ValueError("Must specify exactly one filename")
print(json.dumps(bytecode)) # noqa: T201
response = execute_bytecode(bytecode, globals=None, timeout=5, team=None, debug="--debug" in modifiers)
for line in response.stdout:
print(line) # noqa: T201

elif "--compile" in modifiers:
if len(args) == 3:
target = args[2]
else:
target = filename[:-4] + ".hoge"
elif "--out" in modifiers:
if len(args) != 2:
raise ValueError("Must specify exactly one filename")
print(json.dumps(bytecode)) # noqa: T201

# write bytecode to file
with open(target, "w") as file:
max_length = 120
line = "["
for index, op in enumerate(bytecode):
encoded = json.dumps(op)
if len(line) + len(encoded) > max_length - 2:
elif "--compile" in modifiers:
if len(args) == 3:
target = args[2]
else:
target = filename[:-4] + ".hoge"
if len(args) != 2:
raise ValueError("Must specify exactly one filename")

# write bytecode to file
with open(target, "w") as file:
max_length = 120
line = "["
for index, op in enumerate(bytecode):
encoded = json.dumps(op)
if len(line) + len(encoded) > max_length - 2:
file.write(line + "\n")
line = ""
line += (" " if len(line) > 1 else "") + encoded + ("]" if index == len(bytecode) - 1 else ",")
if line == "[":
file.write(line + "]\n")
elif line != "":
file.write(line + "\n")
line = ""
line += (" " if len(line) > 1 else "") + encoded + ("]" if index == len(bytecode) - 1 else ",")
if line == "[":
file.write(line + "]\n")
elif line != "":
file.write(line + "\n")

else:
raise ValueError("Must specify either --run or --compile")
else:
raise ValueError("Must specify either --run or --compile")
52 changes: 26 additions & 26 deletions posthog/hogql/compiler/test/test_javascript.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,32 @@

class TestJavaScript(BaseTest):
def test_javascript_create(self):
self.assertEqual(to_js_expr("1 + 2"), "(1 + 2)")
self.assertEqual(to_js_expr("1 and 2"), "(1 && 2)")
self.assertEqual(to_js_expr("1 or 2"), "(1 || 2)")
self.assertEqual(to_js_expr("1 or (2 and 1) or 2"), "(1 || (2 && 1) || 2)")
self.assertEqual(to_js_expr("(1 or 2) and (1 or 2)"), "((1 || 2) && (1 || 2))")
self.assertEqual(to_js_expr("not true"), "(!true)")
self.assertEqual(to_js_expr("true"), "true")
self.assertEqual(to_js_expr("false"), "false")
self.assertEqual(to_js_expr("null"), "null")
self.assertEqual(to_js_expr("3.14"), "3.14")
self.assertEqual(to_js_expr("properties.bla"), "properties.bla")
self.assertEqual(to_js_expr("concat('arg', 'another')"), '(String("arg") + String("another"))')
self.assertEqual(to_js_expr("ifNull(properties.email, false)"), "(properties.email ?? false)")
self.assertEqual(to_js_expr("1 = 2"), "(1 == 2)")
self.assertEqual(to_js_expr("1 == 2"), "(1 == 2)")
self.assertEqual(to_js_expr("1 != 2"), "(1 != 2)")
self.assertEqual(to_js_expr("1 < 2"), "(1 < 2)")
self.assertEqual(to_js_expr("1 <= 2"), "(1 <= 2)")
self.assertEqual(to_js_expr("1 > 2"), "(1 > 2)")
self.assertEqual(to_js_expr("1 >= 2"), "(1 >= 2)")
self.assertEqual(to_js_expr("1 in 2"), "(2.includes(1))")
self.assertEqual(to_js_expr("1 not in 2"), "(!2.includes(1))")
self.assertEqual(to_js_expr("match('test', 'e.*')"), 'match("test", "e.*")')
self.assertEqual(to_js_expr("not('test')"), '(!"test")')
self.assertEqual(to_js_expr("or('test', 'test2')"), '("test" || "test2")')
self.assertEqual(to_js_expr("and('test', 'test2')"), '("test" && "test2")')
assert to_js_expr("1 + 2") == "(1 + 2)"
assert to_js_expr("1 and 2") == "(1 && 2)"
assert to_js_expr("1 or 2") == "(1 || 2)"
assert to_js_expr("1 or (2 and 1) or 2") == "(1 || (2 && 1) || 2)"
assert to_js_expr("(1 or 2) and (1 or 2)") == "((1 || 2) && (1 || 2))"
assert to_js_expr("not true") == "(!true)"
assert to_js_expr("true") == "true"
assert to_js_expr("false") == "false"
assert to_js_expr("null") == "null"
assert to_js_expr("3.14") == "3.14"
assert to_js_expr("properties.bla") == "properties.bla"
assert to_js_expr("concat('arg', 'another')"), '(String("arg") + String("another"))'
assert to_js_expr("ifNull(properties.email, false)") == "(properties.email ?? false)"
assert to_js_expr("1 = 2") == "(1 == 2)"
assert to_js_expr("1 == 2") == "(1 == 2)"
assert to_js_expr("1 != 2") == "(1 != 2)"
assert to_js_expr("1 < 2") == "(1 < 2)"
assert to_js_expr("1 <= 2") == "(1 <= 2)"
assert to_js_expr("1 > 2") == "(1 > 2)"
assert to_js_expr("1 >= 2") == "(1 >= 2)"
assert to_js_expr("1 in 2") == "(2.includes(1))"
assert to_js_expr("1 not in 2") == "(!2.includes(1))"
assert to_js_expr("match('test', 'e.*')") == 'match("test", "e.*")'
assert to_js_expr("not('test')") == '(!"test")'
assert to_js_expr("or('test', 'test2')") == '("test" || "test2")'
assert to_js_expr("and('test', 'test2')") == '("test" && "test2")'

def test_javascript_create_not_implemented_error(self):
with self.assertRaises(NotImplementedError) as e:
Expand Down

0 comments on commit 31c0f77

Please sign in to comment.