1
1
mirror of https://github.com/github/semantic.git synced 2024-12-24 15:35:14 +03:00

Use rec so functions can refer to themselves in their bodies.

Code like the following kind is legal in Python:

```python
def recursive(a): return recursive
```

This implies that function and class definitions need to use the Core
`rec` construct so that their bodies have an appropriate entry in the scope.
This commit is contained in:
Patrick Thomson 2019-10-16 17:34:43 -04:00
parent 9f2119c1d9
commit 01b4a23b23
10 changed files with 15 additions and 10 deletions

View File

@ -206,7 +206,8 @@ instance Compile Py.ClassDefinition where
pure (typefn $$ Core.string (coerce n) $$ object $$ contents)
body <- compile pybody buildTypeCall next
let assignClass = Name.named' n :<- body
let coreName = Name.named' n
let assignClass = coreName :<- (rec coreName body)
let continuing = fmap (locate it . (assignClass >>>=))
continuing (local (def n) (cc next))
@ -277,7 +278,7 @@ instance Compile Py.FunctionDefinition where
parameters' <- traverse param parameters
body' <- compile body pure next
-- Build a lambda.
let located = locate it (lams parameters' body')
let located = locate it (rec (Name.named' (Name name)) (lams parameters' body'))
-- Give it a name (below), then augment the current continuation
-- with the new name (with 'def'), so that calling contexts know
-- that we have built an exportable definition.

View File

@ -1,3 +1,3 @@
# CHECK-TREE: { foo <- (\a -> a); #record { foo: foo } }
# CHECK-TREE: { foo <- rec foo = \a -> a; #record { foo: foo } }
def foo(a):
return a

View File

@ -1,4 +1,4 @@
# CHECK-TREE: { foo <- (\a -> a); #record { foo: foo } }
# CHECK-TREE: { foo <- rec foo = (\a -> a); #record { foo: foo } }
def foo(a):
return a

View File

@ -1,4 +1,4 @@
# CHECK-TREE: { foo <- \a -> if a then a else #unit; #record { foo: foo } }
# CHECK-TREE: { foo <- rec foo = \a -> if a then a else #unit; #record { foo: foo } }
def foo(a):
if a: return a

View File

@ -1,4 +1,4 @@
# CHECK-TREE: { const <- \x -> \y -> x; y <- const #true #true; z <- const #false #false; #record { const: const, y : y, z: z, }}
# CHECK-TREE: { const <- rec const = \x -> \y -> x; y <- const #true #true; z <- const #false #false; #record { const: const, y : y, z: z, }}
def const(x, y): return x
y = const(True, True)
z = const(False, False)

View File

@ -1,4 +1,4 @@
# CHECK-TREE: { const <- \a -> \b -> { identity <- \x -> x; identity a }; #record{ const: const }}
# CHECK-TREE: { const <- rec const = \a -> \b -> { identity <- rec identity = \x -> x; identity a }; #record{ const: const }}
def const(a, b):
def identity(x):

View File

@ -1,4 +1,4 @@
# CHECK-TREE: { passthru <- \x -> x; decorated <- \x -> x; decorated = passthru(decorated); #record { passthru: passthru, decorated: decorated }}
# CHECK-TREE: { passthru <- rec passthru = \x -> x; decorated <- rec decorated = \x -> x; decorated = passthru(decorated); #record { passthru: passthru, decorated: decorated }}
def passthru(x):
return x

View File

@ -1,3 +1,3 @@
# CHECK-TREE: { Foo <- __semantic_prelude.type "Foo" __semantic_prelude.object #record {}; #record { Foo: Foo }}
# CHECK-TREE: { Foo <- rec Foo = __semantic_prelude.type "Foo" __semantic_prelude.object #record {}; #record { Foo: Foo }}
class Foo():
pass

View File

@ -1,4 +1,4 @@
# CHECK-TREE: { Foo <- { identity <- \self -> \x -> x; __semantic_prelude.type "Foo" __semantic_prelude.object #record { identity: identity } }; #record { Foo: Foo } }
# CHECK-TREE: { Foo <- rec Foo = { identity <- rec identity = \self -> \x -> x; __semantic_prelude.type "Foo" __semantic_prelude.object #record { identity: identity } }; #record { Foo: Foo } }
class Foo():
def identity(self, x):

View File

@ -0,0 +1,4 @@
# CHECK-TREE: { recursive <- rec recursive = \a -> recursive; #record { recursive: recursive }}
def recursive(a): return recursive
# this should scope correctly in the graph but it doesn't seem to yet