From 5566bac682028f66bc10ec2a5bf100b228042a97 Mon Sep 17 00:00:00 2001 From: Patrick Thomson Date: Fri, 11 Oct 2019 15:02:52 -0400 Subject: [PATCH] Compile class definitions. --- semantic-python/src/Language/Python/Core.hs | 18 ++++++++++++++++-- .../fixtures/3-01-empty-class-definition.py | 3 +++ .../fixtures/3-02-defining-instance-method.py | 5 +++++ 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 semantic-python/test/fixtures/3-01-empty-class-definition.py create mode 100644 semantic-python/test/fixtures/3-02-defining-instance-method.py diff --git a/semantic-python/src/Language/Python/Core.hs b/semantic-python/src/Language/Python/Core.hs index 2fb87f130..2d4aff0d3 100644 --- a/semantic-python/src/Language/Python/Core.hs +++ b/semantic-python/src/Language/Python/Core.hs @@ -1,5 +1,5 @@ {-# LANGUAGE ConstraintKinds, DataKinds, DefaultSignatures, DisambiguateRecordFields, FlexibleContexts, - GeneralizedNewtypeDeriving, KindSignatures, LambdaCase, NamedFieldPuns, OverloadedLists, + GeneralizedNewtypeDeriving, KindSignatures, LambdaCase, NamedFieldPuns, OverloadedLists, OverloadedStrings, PatternSynonyms, StandaloneDeriving, TypeApplications, TypeOperators, ViewPatterns #-} module Language.Python.Core @@ -24,6 +24,7 @@ import Source.Span (Span) import Syntax.Stack (Stack (..)) import qualified Syntax.Stack as Stack import qualified TreeSitter.Python.AST as Py +import Debug.Trace (traceM) -- | Keeps track of the current scope's bindings (so that we can, when -- compiling a class or module, return the list of bound variables as @@ -194,7 +195,20 @@ instance Compile Py.Call where locate it (func $$* args) & cc compile it _ _ = fail ("can't compile Call node with generator expression: " <> show it) -instance Compile Py.ClassDefinition +instance Compile Py.ClassDefinition where + compile _it@Py.ClassDefinition { body = pybody, name = Py.Identifier _ann pyname } cc next = do + traceM "in class def" + let n = Name pyname + let buildTypeCall _next' = do + bindings <- asks @Bindings (toList . unBindings) + let buildName n = (n, pure n) + let contents = record . fmap buildName $ bindings + pure (pure (Name "type") $$ Core.string pyname $$ pure "object" $$ contents) + + body <- compile pybody buildTypeCall next + let called = Name.named' n :<- body + fmap (called >>>=) (local (def n) (cc next)) + instance Compile Py.ComparisonOperator deriving instance Compile Py.CompoundStatement diff --git a/semantic-python/test/fixtures/3-01-empty-class-definition.py b/semantic-python/test/fixtures/3-01-empty-class-definition.py new file mode 100644 index 000000000..bc7abeb03 --- /dev/null +++ b/semantic-python/test/fixtures/3-01-empty-class-definition.py @@ -0,0 +1,3 @@ +# CHECK-TREE: { Foo <- type "Foo" object #record {}; #record { Foo: Foo }} +class Foo(): + pass diff --git a/semantic-python/test/fixtures/3-02-defining-instance-method.py b/semantic-python/test/fixtures/3-02-defining-instance-method.py new file mode 100644 index 000000000..ecefe5313 --- /dev/null +++ b/semantic-python/test/fixtures/3-02-defining-instance-method.py @@ -0,0 +1,5 @@ +# CHECK-TREE: { Foo <- { identity <- \self -> \x -> x; type "Foo" object #record { identity: identity } }; #record { Foo: Foo } } + +class Foo(): + def identity(self, x): + return x