From fa00f3528a3c512375477a65f428e61e7306cdbb Mon Sep 17 00:00:00 2001 From: Marius Andra Date: Fri, 14 Jun 2024 17:27:26 +0200 Subject: [PATCH] feat(hog): empty, not empty (#22980) --- hogvm/__tests__/__snapshots__/stl.hoge | 30 ++++++++++---- hogvm/__tests__/__snapshots__/stl.stdout | 40 ++++++++++++++++++ hogvm/__tests__/__snapshots__/tuples.hoge | 12 +++--- hogvm/__tests__/__snapshots__/tuples.stdout | 1 + hogvm/__tests__/stl.hog | 45 +++++++++++++++++++-- hogvm/__tests__/tuples.hog | 1 + hogvm/python/stl/__init__.py | 15 +++++++ hogvm/typescript/package.json | 2 +- hogvm/typescript/src/stl/print.ts | 3 ++ hogvm/typescript/src/stl/stl.ts | 24 ++++++++++- 10 files changed, 154 insertions(+), 19 deletions(-) diff --git a/hogvm/__tests__/__snapshots__/stl.hoge b/hogvm/__tests__/__snapshots__/stl.hoge index df6a1ac4eef7c..b55b0303ac63a 100644 --- a/hogvm/__tests__/__snapshots__/stl.hoge +++ b/hogvm/__tests__/__snapshots__/stl.hoge @@ -1,9 +1,25 @@ ["_h", 32, "-- empty, notEmpty, length, lower, upper, reverse --", 2, "print", 1, 35, 32, "234", 2, "notEmpty", 1, 32, "", 2, "empty", 1, 3, 2, 40, 9, 32, "123", 2, "length", 1, 2, "print", 1, 35, 32, "tdd4gh", 32, "Tdd4gh", 2, "lower", 1, -11, 40, 9, 32, "test", 2, "upper", 1, 2, "print", 1, 35, 32, "spinner", 2, "reverse", 1, 2, "print", 1, 35, 32, -"http://www.google.com", 2, "encodeURLComponent", 1, 2, "print", 1, 35, 32, "tom & jerry", 2, "encodeURLComponent", 1, -2, "print", 1, 35, 32, "http://www.google.com", 2, "encodeURLComponent", 1, 2, "decodeURLComponent", 1, 2, "print", 1, -35, 32, "tom & jerry", 2, "encodeURLComponent", 1, 2, "decodeURLComponent", 1, 2, "print", 1, 35, 32, -"http://www.google.com", 2, "base64Encode", 1, 2, "print", 1, 35, 32, "tom & jerry", 2, "base64Encode", 1, 2, "print", -1, 35, 32, "http://www.google.com", 2, "base64Encode", 1, 2, "base64Decode", 1, 2, "print", 1, 35, 32, "tom & jerry", 2, -"base64Encode", 1, 2, "base64Decode", 1, 2, "print", 1, 35] +11, 40, 9, 32, "test", 2, "upper", 1, 2, "print", 1, 35, 32, "spinner", 2, "reverse", 1, 2, "print", 1, 35, 32, "", 2, +"print", 1, 35, 32, "-- encodeURLComponent, decodeURLComponent --", 2, "print", 1, 35, 32, "http://www.google.com", 2, +"encodeURLComponent", 1, 2, "print", 1, 35, 32, "tom & jerry", 2, "encodeURLComponent", 1, 2, "print", 1, 35, 32, +"http://www.google.com", 2, "encodeURLComponent", 1, 2, "decodeURLComponent", 1, 2, "print", 1, 35, 32, "tom & jerry", +2, "encodeURLComponent", 1, 2, "decodeURLComponent", 1, 2, "print", 1, 35, 32, "", 2, "print", 1, 35, 32, +"-- base64Encode, base64Decode --", 2, "print", 1, 35, 32, "http://www.google.com", 2, "base64Encode", 1, 2, "print", 1, +35, 32, "tom & jerry", 2, "base64Encode", 1, 2, "print", 1, 35, 32, "http://www.google.com", 2, "base64Encode", 1, 2, +"base64Decode", 1, 2, "print", 1, 35, 32, "tom & jerry", 2, "base64Encode", 1, 2, "base64Decode", 1, 2, "print", 1, 35, +32, "", 2, "print", 1, 35, 32, "-- empty --", 2, "print", 1, 35, 31, 2, "empty", 1, 2, "print", 1, 35, 33, 0, 2, +"empty", 1, 2, "print", 1, 35, 33, 1, 2, "empty", 1, 2, "print", 1, 35, 33, -1, 2, "empty", 1, 2, "print", 1, 35, 34, +0.0, 2, "empty", 1, 2, "print", 1, 35, 34, 0.01, 2, "empty", 1, 2, "print", 1, 35, 32, "", 2, "empty", 1, 2, "print", 1, +35, 32, "string", 2, "empty", 1, 2, "print", 1, 35, 32, "0", 2, "empty", 1, 2, "print", 1, 35, 43, 0, 2, "empty", 1, 2, +"print", 1, 35, 42, 0, 2, "empty", 1, 2, "print", 1, 35, 2, "tuple", 0, 2, "empty", 1, 2, "print", 1, 35, 33, 0, 2, +"tuple", 1, 2, "empty", 1, 2, "print", 1, 35, 33, 2, 33, 1, 2, "tuple", 2, 2, "empty", 1, 2, "print", 1, 35, 32, "", 2, +"print", 1, 35, 32, "-- notEmpty --", 2, "print", 1, 35, 31, 2, "notEmpty", 1, 2, "print", 1, 35, 33, 0, 2, "notEmpty", +1, 2, "print", 1, 35, 33, 1, 2, "notEmpty", 1, 2, "print", 1, 35, 33, -1, 2, "notEmpty", 1, 2, "print", 1, 35, 34, 0.0, +2, "notEmpty", 1, 2, "print", 1, 35, 34, 0.01, 2, "notEmpty", 1, 2, "print", 1, 35, 32, "", 2, "notEmpty", 1, 2, +"print", 1, 35, 32, "string", 2, "notEmpty", 1, 2, "print", 1, 35, 32, "0", 2, "notEmpty", 1, 2, "print", 1, 35, 43, 0, +2, "notEmpty", 1, 2, "print", 1, 35, 42, 0, 2, "notEmpty", 1, 2, "print", 1, 35, 2, "tuple", 0, 2, "notEmpty", 1, 2, +"print", 1, 35, 33, 0, 2, "tuple", 1, 2, "notEmpty", 1, 2, "print", 1, 35, 33, 2, 33, 1, 2, "tuple", 2, 2, "notEmpty", +1, 2, "print", 1, 35, 32, "", 2, "print", 1, 35, 32, "-- replaceAll, replaceOne --", 2, "print", 1, 35, 32, "L", 32, +"l", 32, "hello world", 2, "replaceAll", 3, 2, "print", 1, 35, 32, "L", 32, "l", 32, "hello world", 2, "replaceOne", 3, +2, "print", 1, 35] diff --git a/hogvm/__tests__/__snapshots__/stl.stdout b/hogvm/__tests__/__snapshots__/stl.stdout index 762eff9197ef2..5d85f96594bf7 100644 --- a/hogvm/__tests__/__snapshots__/stl.stdout +++ b/hogvm/__tests__/__snapshots__/stl.stdout @@ -2,11 +2,51 @@ 3 TEST rennips + +-- encodeURLComponent, decodeURLComponent -- http%3A%2F%2Fwww.google.com tom%20%26%20jerry http://www.google.com tom & jerry + +-- base64Encode, base64Decode -- aHR0cDovL3d3dy5nb29nbGUuY29t dG9tICYgamVycnk= http://www.google.com tom & jerry + +-- empty -- +true +true +false +false +true +false +true +false +false +true +true +true +false +false + +-- notEmpty -- +false +false +true +true +false +true +false +true +true +false +false +false +true +true + +-- replaceAll, replaceOne -- +heLLo worLd +heLlo world diff --git a/hogvm/__tests__/__snapshots__/tuples.hoge b/hogvm/__tests__/__snapshots__/tuples.hoge index c2efc1fd7f680..e5577761448b6 100644 --- a/hogvm/__tests__/__snapshots__/tuples.hoge +++ b/hogvm/__tests__/__snapshots__/tuples.hoge @@ -1,6 +1,6 @@ -["_h", 33, 1, 33, 2, 33, 3, 44, 3, 2, "print", 1, 35, 33, 1, 32, "2", 33, 3, 44, 3, 2, "print", 1, 35, 33, 1, 33, 2, 33, -3, 44, 2, 33, 4, 44, 3, 2, "print", 1, 35, 33, 1, 33, 2, 33, 3, 33, 4, 44, 2, 44, 2, 33, 5, 44, 3, 2, "print", 1, 35, -33, 1, 33, 2, 33, 3, 44, 3, 36, 0, 33, 1, 45, 2, "print", 1, 35, 33, 1, 33, 2, 33, 3, 33, 4, 44, 2, 44, 2, 33, 5, 44, 3, -33, 1, 45, 33, 1, 45, 33, 1, 45, 2, "print", 1, 35, 33, 1, 33, 2, 33, 3, 33, 4, 44, 2, 44, 2, 33, 5, 44, 3, 33, 1, 45, -33, 1, 45, 33, 1, 45, 2, "print", 1, 35, 33, 1, 33, 1, 33, 2, 33, 3, 33, 4, 44, 2, 44, 2, 33, 5, 44, 3, 33, 1, 45, 33, -1, 45, 33, 1, 45, 6, 2, "print", 1, 35, 35] +["_h", 2, "tuple", 0, 2, "print", 1, 35, 33, 1, 33, 2, 33, 3, 44, 3, 2, "print", 1, 35, 33, 1, 32, "2", 33, 3, 44, 3, 2, +"print", 1, 35, 33, 1, 33, 2, 33, 3, 44, 2, 33, 4, 44, 3, 2, "print", 1, 35, 33, 1, 33, 2, 33, 3, 33, 4, 44, 2, 44, 2, +33, 5, 44, 3, 2, "print", 1, 35, 33, 1, 33, 2, 33, 3, 44, 3, 36, 0, 33, 1, 45, 2, "print", 1, 35, 33, 1, 33, 2, 33, 3, +33, 4, 44, 2, 44, 2, 33, 5, 44, 3, 33, 1, 45, 33, 1, 45, 33, 1, 45, 2, "print", 1, 35, 33, 1, 33, 2, 33, 3, 33, 4, 44, +2, 44, 2, 33, 5, 44, 3, 33, 1, 45, 33, 1, 45, 33, 1, 45, 2, "print", 1, 35, 33, 1, 33, 1, 33, 2, 33, 3, 33, 4, 44, 2, +44, 2, 33, 5, 44, 3, 33, 1, 45, 33, 1, 45, 33, 1, 45, 6, 2, "print", 1, 35, 35] diff --git a/hogvm/__tests__/__snapshots__/tuples.stdout b/hogvm/__tests__/__snapshots__/tuples.stdout index 182639c8af8be..a602254cd3101 100644 --- a/hogvm/__tests__/__snapshots__/tuples.stdout +++ b/hogvm/__tests__/__snapshots__/tuples.stdout @@ -1,3 +1,4 @@ +tuple() (1, 2, 3) (1, '2', 3) (1, (2, 3), 4) diff --git a/hogvm/__tests__/stl.hog b/hogvm/__tests__/stl.hog index add53abc003b5..7cb6c0fdba908 100644 --- a/hogvm/__tests__/stl.hog +++ b/hogvm/__tests__/stl.hog @@ -2,15 +2,52 @@ print('-- empty, notEmpty, length, lower, upper, reverse --') if (empty('') and notEmpty('234')) print(length('123')) if (lower('Tdd4gh') == 'tdd4gh') print(upper('test')) print(reverse('spinner')) - +print('') +print('-- encodeURLComponent, decodeURLComponent --') print(encodeURLComponent('http://www.google.com')) print(encodeURLComponent('tom & jerry')) - print(decodeURLComponent(encodeURLComponent('http://www.google.com'))) print(decodeURLComponent(encodeURLComponent('tom & jerry'))) - +print('') +print('-- base64Encode, base64Decode --') print(base64Encode('http://www.google.com')) print(base64Encode('tom & jerry')) - print(base64Decode(base64Encode('http://www.google.com'))) print(base64Decode(base64Encode('tom & jerry'))) +print('') +print('-- empty --') +print(empty(null)) +print(empty(0)) +print(empty(1)) +print(empty(-1)) +print(empty(0.0)) +print(empty(0.01)) +print(empty('')) +print(empty('string')) +print(empty('0')) +print(empty([])) +print(empty({})) +print(empty(tuple())) +print(empty(tuple(0))) +print(empty(tuple(1,2))) +print('') +print('-- notEmpty --') +print(notEmpty(null)) +print(notEmpty(0)) +print(notEmpty(1)) +print(notEmpty(-1)) +print(notEmpty(0.0)) +print(notEmpty(0.01)) +print(notEmpty('')) +print(notEmpty('string')) +print(notEmpty('0')) +print(notEmpty([])) +print(notEmpty({})) +print(notEmpty(tuple())) +print(notEmpty(tuple(0))) +print(notEmpty(tuple(1,2))) +print('') +print('-- replaceAll, replaceOne --') +print(replaceAll('hello world', 'l', 'L')) +print(replaceOne('hello world', 'l', 'L')) + diff --git a/hogvm/__tests__/tuples.hog b/hogvm/__tests__/tuples.hog index e7bd601c7ed2f..da57b0bd497c5 100644 --- a/hogvm/__tests__/tuples.hog +++ b/hogvm/__tests__/tuples.hog @@ -1,3 +1,4 @@ +print(tuple()) print((1, 2, 3)) print((1, '2', 3)) print((1, (2, 3), 4)) diff --git a/hogvm/python/stl/__init__.py b/hogvm/python/stl/__init__.py index 818dc888fa39e..f61674dd3ed1a 100644 --- a/hogvm/python/stl/__init__.py +++ b/hogvm/python/stl/__init__.py @@ -64,6 +64,10 @@ def notEmpty(name: str, args: list[Any], team: Optional["Team"], stdout: Optiona return bool(args[0]) +def _tuple(name: str, args: list[Any], team: Optional["Team"], stdout: Optional[list[str]], timeout: int): + return tuple(args) + + def lower(name: str, args: list[Any], team: Optional["Team"], stdout: Optional[list[str]], timeout: int): return args[0].lower() @@ -135,6 +139,14 @@ def decodeURLComponent( return urllib.parse.unquote(args[0]) +def replaceOne(name: str, args: list[Any], team: Optional["Team"], stdout: Optional[list[str]], timeout: int) -> str: + return args[0].replace(args[1], args[2], 1) + + +def replaceAll(name: str, args: list[Any], team: Optional["Team"], stdout: Optional[list[str]], timeout: int) -> str: + return args[0].replace(args[1], args[2]) + + STL: dict[str, Callable[[str, list[Any], Optional["Team"], list[str] | None, int], Any]] = { "concat": concat, "match": match, @@ -146,6 +158,7 @@ def decodeURLComponent( "length": length, "empty": empty, "notEmpty": notEmpty, + "tuple": _tuple, "lower": lower, "upper": upper, "reverse": reverse, @@ -158,4 +171,6 @@ def decodeURLComponent( "base64Decode": base64Decode, "encodeURLComponent": encodeURLComponent, "decodeURLComponent": decodeURLComponent, + "replaceOne": replaceOne, + "replaceAll": replaceAll, } diff --git a/hogvm/typescript/package.json b/hogvm/typescript/package.json index de1a0b9db0bf3..53c5805ebe241 100644 --- a/hogvm/typescript/package.json +++ b/hogvm/typescript/package.json @@ -1,6 +1,6 @@ { "name": "@posthog/hogvm", - "version": "1.0.12", + "version": "1.0.13", "description": "PostHog Hog Virtual Machine", "types": "dist/index.d.ts", "main": "dist/index.js", diff --git a/hogvm/typescript/src/stl/print.ts b/hogvm/typescript/src/stl/print.ts index 26fad2f4080e9..b70e554a7256e 100644 --- a/hogvm/typescript/src/stl/print.ts +++ b/hogvm/typescript/src/stl/print.ts @@ -42,6 +42,9 @@ export function escapeIdentifier(identifier: string | number): string { export function printHogValue(obj: any): string { if (Array.isArray(obj)) { if ((obj as any).__isHogTuple) { + if (obj.length < 2) { + return `tuple(${obj.map(printHogValue).join(', ')})` + } return `(${obj.map(printHogValue).join(', ')})` } else { return `[${obj.map(printHogValue).join(', ')}]` diff --git a/hogvm/typescript/src/stl/stl.ts b/hogvm/typescript/src/stl/stl.ts index 303ef460ed81b..7966e58ff2d93 100644 --- a/hogvm/typescript/src/stl/stl.ts +++ b/hogvm/typescript/src/stl/stl.ts @@ -27,10 +27,26 @@ export const STL: Record return args[0].length }, empty: (args) => { + if (typeof args[0] === 'object') { + if (Array.isArray(args[0])) { + return args[0].length === 0 + } else if (args[0] === null) { + return true + } else if (args[0] instanceof Map) { + return args[0].size === 0 + } else { + return Object.keys(args[0]).length === 0 + } + } return !args[0] }, notEmpty: (args) => { - return !!args[0] + return !STL.empty(args, 'empty', 0) + }, + tuple: (args) => { + const tuple = args.slice() + ;(tuple as any).__isHogTuple = true + return tuple }, lower: (args) => { return args[0].toLowerCase() @@ -105,6 +121,12 @@ export const STL: Record decodeURLComponent(args) { return decodeURIComponent(args[0]) }, + replaceOne(args) { + return args[0].replace(args[1], args[2]) + }, + replaceAll(args) { + return args[0].replaceAll(args[1], args[2]) + }, } export const ASYNC_STL: Record Promise> = {