From 1b71e04cf316896dec54803df9c5a32f3cf2fddd Mon Sep 17 00:00:00 2001 From: marsninja Date: Fri, 15 Sep 2023 14:14:59 -0400 Subject: [PATCH 1/4] Example in, now have to make lang compliant --- .flake8 | 2 +- .pre-commit-config.yaml | 3 +- examples/manual_code/circle.jac | 77 ++++++++++++++++++++++ examples/manual_code/circle.py | 82 ++++++++++++++++++++++++ jaclang/utils/test.py | 11 ++++ support/jac-lang.org/docs/learn/learn.md | 25 +++++++- 6 files changed, 196 insertions(+), 4 deletions(-) create mode 100644 examples/manual_code/circle.jac create mode 100644 examples/manual_code/circle.py diff --git a/.flake8 b/.flake8 index 7bd2a9dd7..a6de5f7a5 100644 --- a/.flake8 +++ b/.flake8 @@ -1,5 +1,5 @@ [flake8] -exclude = fixtures, __jac_gen__, build +exclude = fixtures, __jac_gen__, build, examples plugins = flake8_import_order, flake8_docstrings, flake8_comprehensions, flake8_bugbear, flake8_annotations, pep8_naming, flake8_simplify max-line-length = 120 ignore = E203, W503, ANN101, ANN102 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bbbe933d3..d5e91c721 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,4 +14,5 @@ repos: rev: 6.1.0 hooks: - id: flake8 - additional_dependencies: [pep8-naming, flake8_import_order, flake8_docstrings, flake8_comprehensions, flake8_bugbear, flake8_annotations, flake8_simplify] \ No newline at end of file + additional_dependencies: [pep8-naming, flake8_import_order, flake8_docstrings, flake8_comprehensions, flake8_bugbear, flake8_annotations, flake8_simplify] + exclude: "examples" \ No newline at end of file diff --git a/examples/manual_code/circle.jac b/examples/manual_code/circle.jac new file mode 100644 index 000000000..674728d5e --- /dev/null +++ b/examples/manual_code/circle.jac @@ -0,0 +1,77 @@ +""" +(Module docstring are Required in a valid Jac) +This module demonstrates a simple circle class and a function to calculate the area of a circle. +""" +import:py math; + +# Module-level global +global RADIUS = 5; + +"""Function to calculate the area of a circle.""" +can calculate_area(radius: float) -> float { + return math.pi * radius * radius; +} + +#* (This is multiline comments in Jac) +Above we have the demonstration of a function to calculate the area of a circle. +Below we have the demonstration of a class to calculate the area of a circle. +*# + +"""Enum for shape types""" +enum ShapeType { + CIRCLE = "Circle"; + UNKNOWN = "Unknown"; +} + +"""Base class for a shape.""" +object Shape { + has shape_type: ShapeType; + + can (shape_type: ShapeType) { + .shape_type = shape_type; + } + + """Abstract method to calculate the area of a shape.""" + can area:abs -> float {} #TODO: add abstract feature +} + + +object Circle(Shape) { + """Circle class inherits from Shape.""" + + can (radius: float) { + .(ShapeType.CIRCLE); + self.radius = radius; + } + + """Overridden method to calculate the area of the circle.""" + can area -> float { + return math.pi * self.radius * self.radius; + } +} + +with entry {c = Circle(RADIUS);} # Global also works here + +with entry:__main__ { # TODO: add name == option abstract feature + # To run the program functionality + print(f"Area of a circle with radius 5: {calculate_area(RADIUS)}") + print(f"Area of a {c.shape_type.value} with radius 5: {c.area()}") + +} + +# TODO: Make tests works +test calculate_area { + expected_area = 78.53981633974483; + assertAlmostEqual(calculate_area(RADIUS), expected_area); +} + +test circle_area { + c = Circle(RADIUS); + expected_area = 78.53981633974483; + assertAlmostEqual(c.area(), expected_area); +} + +test circle_type { + c = Circle(RADIUS); + assertEqual(c.shape_type, ShapeType.CIRCLE); +} \ No newline at end of file diff --git a/examples/manual_code/circle.py b/examples/manual_code/circle.py new file mode 100644 index 000000000..2ce8d4250 --- /dev/null +++ b/examples/manual_code/circle.py @@ -0,0 +1,82 @@ +""" +This module demonstrates a simple circle class and a function to calculate the area of a circle. +(Module docstrings are optional but good practice in python) +""" +from enum import Enum +import math +import unittest + +# Module-level global +RADIUS = 5 + + +def calculate_area(radius: float) -> float: + """Function to calculate the area of a circle.""" + return math.pi * radius * radius + + +# Multiline comments in python feels like a hack +""" +Above we have the demonstration of a function to calculate the area of a circle. +Below we have the demonstration of a class to calculate the area of a circle. +""" + + +# Enum for shape types +class ShapeType(Enum): + CIRCLE = "Circle" + UNKNOWN = "Unknown" + + +class Shape: + """Base class for a shape.""" + + def __init__(self, shape_type: ShapeType): + self.shape_type = shape_type + + def area(self) -> float: + """Returns the area of the shape.""" + pass + + +class Circle(Shape): + """Circle class inherits from Shape.""" + + def __init__(self, radius: float): + super().__init__(ShapeType.CIRCLE) + self.radius = radius + + def area(self) -> float: + """Overridden method to calculate the area of the circle.""" + return math.pi * self.radius * self.radius + + +c = Circle(RADIUS) + +if __name__ == "__main__": + # To run the program functionality + print( + f"Area of a circle with radius {RADIUS} using function: {calculate_area(RADIUS)}" + ) + print( + f"Area of a {c.shape_type.value} with radius {RADIUS} using class: {c.area()}" + ) + + # Uncomment the next line if you want to run the unit tests + # run_tests() + + +# Unit tests below, bad practice in python to have unit tests in the same file as the code +class TestShapesFunctions(unittest.TestCase): + def test_calculate_area(self): + expected_area = 78.53981633974483 + self.assertAlmostEqual(calculate_area(RADIUS), expected_area) + + def test_circle_area(self): + c = Circle(RADIUS) + expected_area = 78.53981633974483 + self.assertAlmostEqual(c.area(), expected_area) + + def test_circle_type(self): + c = Circle(RADIUS) + self.assertEqual(c.shape_type, ShapeType.CIRCLE) diff --git a/jaclang/utils/test.py b/jaclang/utils/test.py index 967ba516c..d4fccd201 100644 --- a/jaclang/utils/test.py +++ b/jaclang/utils/test.py @@ -65,6 +65,17 @@ def self_attach_micro_tests(cls) -> None: cls, method_name, lambda self, f=file_path: self.micro_suite_test(f) ) + directory = os.path.dirname(__file__) + "/../../examples/manual_code" + for filename in os.listdir(directory): + if os.path.isfile(os.path.join(directory, filename)) and filename.endswith( + ".jac" + ): + method_name = f"test_micro_{filename.replace('.jac', '')}" + file_path = os.path.join(directory, filename) + setattr( + cls, method_name, lambda self, f=file_path: self.micro_suite_test(f) + ) + directory = os.path.dirname(__file__) + "/../../examples/guess_game" for filename in os.listdir(directory): if os.path.isfile(os.path.join(directory, filename)) and filename.endswith( diff --git a/support/jac-lang.org/docs/learn/learn.md b/support/jac-lang.org/docs/learn/learn.md index e70147e3a..0ecd65b44 100644 --- a/support/jac-lang.org/docs/learn/learn.md +++ b/support/jac-lang.org/docs/learn/learn.md @@ -1,3 +1,24 @@ -# Learn Jac +# Coding Manual -This section is the primary location to learn all about Jac and how to use it! \ No newline at end of file +Jac is all of pythons goodness wrapped in a language that gives the coder wings. Lets jump right in! + +## Get Jac + +Install Jac. + +```bash +pip install jaclang +``` + +Validate Jac works. + +```bash +echo "with entry { print('hello world'); } > test.jac; jac load -f test.jac; rm test.jac;" +``` + +If that command prints `hello world`, Jac is working. + +Ok now lets jump into learning Jac! +## Modules in Jac + +We start this journey top down. Lets look at a simple but complete program in python and the Jac version. \ No newline at end of file From 093e52cfd3d019d2d9f8d27787346856ffe570f0 Mon Sep 17 00:00:00 2001 From: marsninja Date: Sat, 16 Sep 2023 08:59:47 -0400 Subject: [PATCH 2/4] Abstract keyword implemented --- README.md | 197 +++++++++++++++++- examples/manual_code/circle.jac | 6 +- jaclang/jac/absyntree.py | 2 + jaclang/jac/constant.py | 1 + jaclang/jac/lexer.py | 4 +- jaclang/jac/parser.py | 13 +- jaclang/jac/passes/blue/ast_build_pass.py | 61 ++++++ support/jac-lang.org/docs/index.md | 8 +- .../docs/learn/coders/defs_decls.md | 3 + support/jac-lang.org/docs/why.md | 4 +- .../jac-lang.org/jac_syntax_highlighter.py | 3 +- .../jac/syntaxes/jac.tmLanguage.json | 2 +- 12 files changed, 284 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index a7656845f..afafdd505 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,197 @@ -# The Jac Programming Language and Jaseci Core +# Getting Started with JacLang -The next generation is upon us... (In ideation and specification phase) +Welcome to JacLang, a unique and powerful programming language that runs on top of Python. To get you started, this guide will walk you through the process of installation, running Jac files, and importing Jac into existing Python modules. -Get to the docs, check the guidelines on how to contribute. +## Installation -## Getting Docs Up Locally +Firstly, you'll need to install JacLang. You can do this easily through Python's package manager, pip. Run the following command: -Go to `/docs` base dir and run +```bash +pip install jaclang +``` + +And from source simply use, ```bash -yarn install -yarn start +pip install -e . +``` + +Upon successful installation, you'll have a script named `jac` at your disposal. This script is used to load and run `.jac` files. + +## Running Jac Files + +Here's how you can use `jac`: + +- To simply load a sample Jac module and exit, run: + ```bash + jac load -f sample.jac + ``` + +- To load a sample Jac module and execute a particular function (considered the entrypoint for execution in Jac), run: + ```bash + jac run -f sample.jac -e my_func + ``` + +Now Try it with this example jac program with both load and calling `test_run` + +```jac +"""Example of simple walker walking nodes.""" + +node item { + has value: int; +} + +walker Creator { + has count: int = 0; + can create with |:n:item entry { + ++> spawn :n:item; + .count += 1; + if .count < 10 { + visit -->; + } + } +} + +walker Walk { + has count: int = 0; + can skip_root with entry { visit -->; } + can step with :n:item entry { + .value = .count; + .count += 1; + visit --> else { + f"Final Value: {.value-1}" |> print; + "Done walking." |> print; + disengage; + } + f"Value: {.value-1}" |> print; + } +} + +can test_run { + spawn :w:Creator |> ; + spawn :w:Walk |> ; +} + +with entry { + |> test_run; +} ``` -For instructions on installing `yarn`, start on that journey with [their instructions](https://yarnpkg.com/getting-started/install). \ No newline at end of file +## Integrating Jac into Python Modules + +JacLang also provides a seamless way to import Jac into existing Python modules through library functions. Here's an example: + +```python +"""CLI for jaclang.""" +from jaclang import jac_purple_import as jac_import + +cli = jac_import("cli") +cmds = jac_import("cmds") + +cli.cmd_registry = cmds.cmd_reg # type: ignore +``` + +In the above code snippet, `cli` and `cmds` are modules that are imported similar to how you'd typically import modules in Python, i.e., `import cli` or `import cmds`. + +Below is a sample `cli.jac` file to provide some insight into how Jac code looks: + +```jac +""" +This is the implementation of the command line interface tool for the +Jac language. It's built with the Jac language via bootstraping and +represents the first such complete Jac program. +""" + +import:py inspect; +import:py argparse; +import:py cmd; +include:jac impl.cli_impl; + +object Command { + has func: callable, + sig: inspect.Signature; + + can:private init(func: callable); + can call(*args: list, **kwargs: dict); +} + + +object CommandRegistry { + has:private registry: dict[str, Command], + sub_parsers: argparse._SubParsersActionp; + has:public parser: argparse.ArgumentParser; + + can init; + can register(func: callable); + can get(name: str) -> Command; + can items -> dict[str, Command]; +} + + +object CommandShell:cmd.Cmd { + static has intro: str = "Welcome to the Jac CLI!", + prompt: str = "jac> "; + has cmd_reg: CommandRegistry; + + can init (cmd_reg: CommandRegistry); + can do_exit(arg: list) -> bool; + can default(line: str); +} + +global cmd_registry = |> CommandRegistry; +can start_cli; +``` + +That's all you need to get started with JacLang. As you delve into this new language, you'll discover how it beautifully combines the power of Python with a modern and intuitive syntax. Happy coding! + +## Installing JacLang Extension in Visual Studio Code (VSCode) + +In addition to setting up JacLang itself, you may also want to take advantage of the JacLang language extension for Visual Studio Code (VSCode). This will give you enhanced code highlighting, autocomplete, and other useful language features within your VSCode environment. + +Here's a step-by-step guide on how to package and install the JacLang VSCode extension. + +### Setting Up VSCE + +To create the VSIX file for the extension, you'll need `vsce`, a command-line tool for packaging VSCode extensions. If you don't have it installed already, follow these steps: + +1. Ensure that you have Node.js (>= 0.10.x) and npm installed on your machine. + +2. Open a terminal (or command prompt) and install `vsce` globally by running the following command: + + ```bash + npm install -g vsce + ``` + +### Packaging the Extension + +Once you have `vsce` set up, navigate to the JacLang extension directory in your local JacLang repository by running: + +```bash +cd /path/to/repo/jaclang/support/vscode_ext/jac +``` + +In the `jac` directory, package the extension into a VSIX file by running: + +```bash +vsce package +``` + +This will create a `.vsix` file, which is the packaged extension. + +### Installing the VSIX File in VSCode + +To install the packaged JacLang extension in VSCode: + +1. Open Visual Studio Code. + +2. Click on the Extensions view icon on the Sidebar (or press `Ctrl+Shift+X`). + +3. Click on the three-dot menu (`...`) in the top-right corner of the Extensions view. + +4. Select `Install from VSIX...` from the dropdown menu. + +5. In the file picker, find and select the `.vsix` file you created earlier and click `Open`. + +6. After a brief moment, the extension will be installed. You might have to reload VSCode for the changes to take effect. + +Now, you're all set to use the JacLang language extension in your VSCode editor! Enjoy your enhanced JacLang development experience. diff --git a/examples/manual_code/circle.jac b/examples/manual_code/circle.jac index 674728d5e..db26381d7 100644 --- a/examples/manual_code/circle.jac +++ b/examples/manual_code/circle.jac @@ -19,8 +19,8 @@ Below we have the demonstration of a class to calculate the area of a circle. """Enum for shape types""" enum ShapeType { - CIRCLE = "Circle"; - UNKNOWN = "Unknown"; + CIRCLE = "Circle", + UNKNOWN = "Unknown" } """Base class for a shape.""" @@ -32,7 +32,7 @@ object Shape { } """Abstract method to calculate the area of a shape.""" - can area:abs -> float {} #TODO: add abstract feature + can area -> float abstract; } diff --git a/jaclang/jac/absyntree.py b/jaclang/jac/absyntree.py index c09698041..f8b6349c0 100644 --- a/jaclang/jac/absyntree.py +++ b/jaclang/jac/absyntree.py @@ -390,6 +390,7 @@ def __init__( is_func: bool, is_async: bool, is_static: bool, + is_abstract: bool, doc: Optional[Token], decorators: Optional[Decorators], access: Optional[Token], @@ -407,6 +408,7 @@ def __init__( self.is_func = is_func self.is_async = is_async self.is_static = is_static + self.is_abstract = is_abstract self.doc = doc self.decorators = decorators diff --git a/jaclang/jac/constant.py b/jaclang/jac/constant.py index ed5f8d833..9c746dd42 100644 --- a/jaclang/jac/constant.py +++ b/jaclang/jac/constant.py @@ -76,6 +76,7 @@ class Tokens(str, Enum): TYP_ANY = "TYP_ANY" TYP_TYPE = "TYP_TYPE" KW_FREEZE = "KW_FREEZE" + KW_ABSTRACT = "KW_ABSTRACT" KW_OBJECT = "KW_OBJECT" KW_ENUM = "KW_ENUM" KW_NODE = "KW_NODE" diff --git a/jaclang/jac/lexer.py b/jaclang/jac/lexer.py index 784966967..9a3b5bd07 100644 --- a/jaclang/jac/lexer.py +++ b/jaclang/jac/lexer.py @@ -44,6 +44,7 @@ def __init__( "TYP_ANY", "TYP_TYPE", "KW_FREEZE", + "KW_ABSTRACT", "KW_OBJECT", "KW_ENUM", "KW_NODE", @@ -211,7 +212,8 @@ def __init__( NAME["bytes"] = "TYP_BYTES" # type: ignore NAME["any"] = "TYP_ANY" # type: ignore NAME["type"] = "TYP_TYPE" # type: ignore - NAME["freeze"] = "KW_FREEZE" # type: ignore + NAME["froz"] = "KW_FREEZE" # type: ignore + NAME["abstract"] = "KW_ABSTRACT" # type: ignore NAME["object"] = "KW_OBJECT" # type: ignore NAME["enum"] = "KW_ENUM" # type: ignore NAME["node"] = "KW_NODE" # type: ignore diff --git a/jaclang/jac/parser.py b/jaclang/jac/parser.py index d1020be20..3066cefc1 100644 --- a/jaclang/jac/parser.py +++ b/jaclang/jac/parser.py @@ -30,7 +30,7 @@ def __init__( self.ir: ast.AstNode = parse_tree_to_ast(self.ir) tokens = JacLexer.tokens - # debugfile = "parser.out" + debugfile = "parser.out" # All mighty start rule # --------------------- @@ -311,6 +311,16 @@ def ability_def(self, p: YaccProduction) -> YaccProduction: """Ability rule.""" return p + @_( + "doc_tag static_tag KW_CAN access_tag all_refs event_clause KW_ABSTRACT SEMI", + "doc_tag static_tag KW_CAN access_tag all_refs func_decl KW_ABSTRACT SEMI", + "doc_tag decorators static_tag KW_CAN access_tag all_refs event_clause KW_ABSTRACT SEMI", + "doc_tag decorators static_tag KW_CAN access_tag all_refs func_decl KW_ABSTRACT SEMI", + ) + def abstract_ability(self, p: YaccProduction) -> YaccProduction: + """Abstract ability rule.""" + return p + @_( "KW_WITH KW_ENTRY return_type_tag", "KW_WITH KW_EXIT return_type_tag", @@ -424,6 +434,7 @@ def member_stmt_list(self, p: YaccProduction) -> YaccProduction: @_( "has_stmt", "ability", + "abstract_ability", ) def member_stmt(self, p: YaccProduction) -> YaccProduction: """Attribute statement rule.""" diff --git a/jaclang/jac/passes/blue/ast_build_pass.py b/jaclang/jac/passes/blue/ast_build_pass.py index 9d3922359..21d85e1c1 100644 --- a/jaclang/jac/passes/blue/ast_build_pass.py +++ b/jaclang/jac/passes/blue/ast_build_pass.py @@ -530,6 +530,7 @@ def exit_ability_decl(self, node: ast.AstNode) -> None: doc=node.kid[0], access=node.kid[2], is_static=node.kid[1], + is_abstract=False, name_ref=node.kid[3], body=node.kid[-1] if isinstance(node.kid[-1], ast.CodeBlock) else None, signature=node.kid[-2], @@ -560,6 +561,7 @@ def exit_ability_decl_decor(self, node: ast.AstNode) -> None: doc=node.kid[0], decorators=node.kid[1], is_static=node.kid[2], + is_abstract=False, access=node.kid[3], name_ref=node.kid[4], body=node.kid[-1] if isinstance(node.kid[-1], ast.CodeBlock) else None, @@ -598,6 +600,65 @@ def exit_ability_def(self, node: ast.AstNode) -> None: ), ) + def exit_abstract_ability(self, node: ast.AstNode) -> None: + """Grammar rule. + + abstract_ability -> doc_tag decorators static_tag KW_CAN access_tag all_refs func_decl KW_ABSTRACT SEMI + abstract_ability -> doc_tag decorators static_tag KW_CAN access_tag all_refs event_clause KW_ABSTRACT SEMI + abstract_ability -> doc_tag static_tag KW_CAN access_tag all_refs func_decl KW_ABSTRACT SEMI + abstract_ability -> doc_tag static_tag KW_CAN access_tag all_refs event_clause KW_ABSTRACT SEMI + """ + if isinstance(node.kid[1], ast.Decorators): + del node.kid[3] + replace_node( + node, + ast.Ability( + doc=node.kid[0], + decorators=node.kid[1], + is_static=node.kid[2], + is_abstract=True, + access=node.kid[3], + name_ref=node.kid[4], + body=node.kid[-1] + if isinstance(node.kid[-1], ast.CodeBlock) + else None, + signature=node.kid[-2], + is_func=isinstance(node.kid[-2], ast.FuncSignature), + is_async=False, + parent=node.parent, + mod_link=self.mod_link, + kid=node.kid, + line=node.line, + ), + ) + if isinstance(node.kid[-1], ast.Token): + del node.kid[-1] + else: + del node.kid[2] + replace_node( + node, + ast.Ability( + doc=node.kid[0], + access=node.kid[2], + is_static=node.kid[1], + is_abstract=False, + name_ref=node.kid[3], + body=node.kid[-1] + if isinstance(node.kid[-1], ast.CodeBlock) + else None, + signature=node.kid[-2], + is_func=isinstance(node.kid[-2], ast.FuncSignature), + is_async=False, + decorators=None, + parent=node.parent, + mod_link=self.mod_link, + kid=node.kid, + line=node.line, + ), + ) + if isinstance(node.kid[-1], ast.Token): + del node.kid[-1] + def exit_event_clause(self, node: ast.AstNode) -> None: """Grammar rule. diff --git a/support/jac-lang.org/docs/index.md b/support/jac-lang.org/docs/index.md index c1c01935c..e61e1ac20 100644 --- a/support/jac-lang.org/docs/index.md +++ b/support/jac-lang.org/docs/index.md @@ -1,8 +1,8 @@ # Welcome to Jac -**Jac** combines the power and flexibility of Python's ecosystem and 'pythonic' coding style with a unique 'jactastic' approach to programming. It draws inspiration from a variety of programming languages to improve upon Python to create an engaging, productive, and intuitive coding experience, giving the coder all of python's power, plus superpowers. +**Jac** combines the power and flexibility of Python's ecosystem and 'pythonic' coding style with a unique 'jactastic' approach to programming. It draws inspiration from a variety of programming languages to improve upon Python to create an engaging, productive, and intuitive coding experience, giving the coder all of python's power, plus superpowers. Additionally, Jac introduces a keystone innovation that may prove to be a monumental advancement in programming languages called the **Data Spatial Programming Model**. -A keystone innovation in Jac is what may prove to be a monumental advancement in programming languages called the **Data Spatial Programming Model**. Just as Object-Oriented Programming (OOP) brought a higher level of abstraction to C and Fortran's functions offered a new way to manage assembly code, Jac introduces Data Spatial Programming constructs expanding on the concept of OOP. This new model is a higher-level abstraction that lets programmers rethink how they interact with data structures, and enable new ways of thinking and being productive. +Just as Object-Oriented Programming (OOP) brought a higher level of abstraction to C and Fortran's functions offered a new way to manage assembly code, Jac introduces Data Spatial Programming constructs expanding on the concept of OOP. This new model is a higher-level abstraction that lets programmers rethink how they interact with data structures, and enable new ways of thinking and being productive. That being said, Jac was meticulously designed to provide a seamless gradient of expressiveness allowing coders to code in a familiar pythonic style, while using as much or as little data spatial semantics as they'd like. @@ -10,8 +10,10 @@ That being said, Jac was meticulously designed to provide a seamless gradient of Jac's design encapsulates a love for the world of programming, computers, and code. It captures the spirit of what makes coding joyful while expanding upon the foundation laid by the beloved language - Python. At its core, Jac is a love letter to Python and modern coding. It inherits the clean syntax, flexibility, and broad applicability that makes Python one of the most popular programming languages in the world while being designed to give us coders new (and old) superpowers. +Update: Jac is contemplating targeting Mojo's language abstractions as well iff it is properly open sourced. + ## A New Home Language -The goal of Jac is to serve as a home language for a coders lifestyle. Jac is built for us, folks who love python, and folks who are serious hackers. It is the language that I've always wanted and one that I believe you will enjoy too. We are looking forward to seeing what you will create with Jac, and how you will add to its evolving story. +The goal of Jac is to serve as a home language for a coders lifestyle. Jac is built for us, folks who love python, see coding as beauty, and are serious hackers aiming to launch everything they do to the world. It is the language that I've always wanted and one that I believe you will enjoy too. We are looking forward to seeing what you will create with Jac, and how you will add to its evolving story. Join us on this exciting journey. Let's make code art with Jac. \ No newline at end of file diff --git a/support/jac-lang.org/docs/learn/coders/defs_decls.md b/support/jac-lang.org/docs/learn/coders/defs_decls.md index c2e55bbe3..5cf2ce2b3 100644 --- a/support/jac-lang.org/docs/learn/coders/defs_decls.md +++ b/support/jac-lang.org/docs/learn/coders/defs_decls.md @@ -52,11 +52,14 @@ First lets look at the declarations ``` ### Definitions in Separate File +**jaclang/jac/passes/purple/impl/purple_pygen_pass_impl.jac** ```jac --8<-- "jaclang/jac/passes/purple/impl/purple_pygen_pass_impl.jac" ``` ### Comparison with Python + +Now lets take a look at a similar pass written in pure python. This is pep8 compliant python following a large number of recommended conventions. Experience its readability in seeing the interface of the class. (point: reading the interface and implementation together is not nice on the eyes.) ```python --8<-- "jaclang/jac/passes/blue/decl_def_match_pass.py" ``` diff --git a/support/jac-lang.org/docs/why.md b/support/jac-lang.org/docs/why.md index 3bd58df45..08b0484bf 100644 --- a/support/jac-lang.org/docs/why.md +++ b/support/jac-lang.org/docs/why.md @@ -11,8 +11,8 @@ Jac's builds upon Python much like Typescript or Elm builds upon Javascript. How Jac doesn't have a big backing company (yet), nor a team of paid coders in a company, nor vast resources to fund the project as many successful languages have had. What is guaranteed is the fact that there's a deep reservoir of determination in Jac's creator, and a couple brilliant coders around Jac who are committed to the vision and excited to see what the future holds. -We're very open and welcoming of anyone who might be open to catching the Jac bug. If you're interested in being part of this project and learn more, please feel free to reach out. We'd love to hear from you. We have a journey ahead of us, but with dedication and collaboration, we're confident we can make Jac a beloved part of every coder's toolkit. +We're very open and welcoming of anyone who might be open to catching the Jac bug. If you're interested in being part of this project and learn more, please feel free to reach out. We'd love to hear from you. We have quite a journey ahead of us, but with dedication and collaboration, we're confident we can make Jac a beloved part of every coder's toolkit. ## About Jac's Creator -Hello, I'm Jason Mars, the lead creator and BDFL of Jac and it's data spatial programming model. I'm a computer enthusiast, a comp. sci. prof, a tech entrepreneur, an avid coder, a gamer, etc. I aim to bring the insights I've gain through these roles to the creation of Jac to make it useful, practical, and beautiful, oh and FUN!! \ No newline at end of file +Hello, I'm Jason Mars, the creator and BDFL (for now at least) of Jac and it's data spatial programming model. I'm a computer enthusiast, a comp. sci. prof, a tech entrepreneur, an avid coder, a gamer, etc. I aim to bring the insights I've gain through these roles to the creation of Jac to make it useful, practical, and beautiful, oh and FUN!! \ No newline at end of file diff --git a/support/jac-lang.org/jac_syntax_highlighter.py b/support/jac-lang.org/jac_syntax_highlighter.py index 1d0c074fc..4404243a8 100644 --- a/support/jac-lang.org/jac_syntax_highlighter.py +++ b/support/jac-lang.org/jac_syntax_highlighter.py @@ -316,7 +316,8 @@ def fstring_rules(ttype): "as", "with", # ----- - "freeze", + "froz", + "abstract", "ignore", "visit", "revisit", diff --git a/support/vscode_ext/jac/syntaxes/jac.tmLanguage.json b/support/vscode_ext/jac/syntaxes/jac.tmLanguage.json index f6d5b0271..69d567c3b 100644 --- a/support/vscode_ext/jac/syntaxes/jac.tmLanguage.json +++ b/support/vscode_ext/jac/syntaxes/jac.tmLanguage.json @@ -583,7 +583,7 @@ }, { "name": "storage.modifier.declaration.jac", - "match": "(?x)\n \\b(? Date: Sat, 16 Sep 2023 09:13:39 -0400 Subject: [PATCH 3/4] Parsing parses --- examples/manual_code/circle.jac | 17 ++++----- jaclang/jac/absyntree.py | 6 ++-- jaclang/jac/parser.py | 5 ++- jaclang/jac/passes/blue/ast_build_pass.py | 41 +++++++++++++++------- jaclang/jac/passes/blue/blue_pygen_pass.py | 14 ++++++-- 5 files changed, 57 insertions(+), 26 deletions(-) diff --git a/examples/manual_code/circle.jac b/examples/manual_code/circle.jac index db26381d7..f0ba9b9ea 100644 --- a/examples/manual_code/circle.jac +++ b/examples/manual_code/circle.jac @@ -36,7 +36,7 @@ object Shape { } -object Circle(Shape) { +object Circle:Shape { """Circle class inherits from Shape.""" can (radius: float) { @@ -54,24 +54,25 @@ with entry {c = Circle(RADIUS);} # Global also works here with entry:__main__ { # TODO: add name == option abstract feature # To run the program functionality - print(f"Area of a circle with radius 5: {calculate_area(RADIUS)}") - print(f"Area of a {c.shape_type.value} with radius 5: {c.area()}") - + print(f"Area of a circle with radius 5: {calculate_area(RADIUS)}"); + print(f"Area of a {c.shape_type.value} with radius 5: {c.area()}"); } -# TODO: Make tests works -test calculate_area { +test calculate_area +"Tests for the calculate_area function." { expected_area = 78.53981633974483; assertAlmostEqual(calculate_area(RADIUS), expected_area); } -test circle_area { +test circle_area +"Tests for the area method of the Circle class." { c = Circle(RADIUS); expected_area = 78.53981633974483; assertAlmostEqual(c.area(), expected_area); } -test circle_type { +test circle_type +"Tests for the shape_type attribute of the Circle class." { c = Circle(RADIUS); assertEqual(c.shape_type, ShapeType.CIRCLE); } \ No newline at end of file diff --git a/jaclang/jac/absyntree.py b/jaclang/jac/absyntree.py index f8b6349c0..614c2fe1a 100644 --- a/jaclang/jac/absyntree.py +++ b/jaclang/jac/absyntree.py @@ -175,8 +175,9 @@ class ModuleCode(AstNode): def __init__( self, - doc: Optional["Token"], - body: "CodeBlock", + doc: Optional[Token], + name: Optional[Name], + body: CodeBlock, parent: Optional[AstNode], mod_link: Optional[Module], kid: list[AstNode], @@ -185,6 +186,7 @@ def __init__( ) -> None: """Initialize test node.""" self.doc = doc + self.name = name self.body = body super().__init__( parent=parent, mod_link=mod_link, kid=kid, line=line, sym_tab=sym_tab diff --git a/jaclang/jac/parser.py b/jaclang/jac/parser.py index 3066cefc1..46f681fbc 100644 --- a/jaclang/jac/parser.py +++ b/jaclang/jac/parser.py @@ -98,7 +98,10 @@ def test(self, p: YaccProduction) -> YaccProduction: """Test rule.""" return p - @_("doc_tag KW_WITH KW_ENTRY code_block") + @_( + "doc_tag KW_WITH KW_ENTRY code_block", + "doc_tag KW_WITH KW_ENTRY sub_name code_block", + ) def mod_code(self, p: YaccProduction) -> YaccProduction: """Module-level free code rule.""" return p diff --git a/jaclang/jac/passes/blue/ast_build_pass.py b/jaclang/jac/passes/blue/ast_build_pass.py index 21d85e1c1..12bd69ec6 100644 --- a/jaclang/jac/passes/blue/ast_build_pass.py +++ b/jaclang/jac/passes/blue/ast_build_pass.py @@ -141,20 +141,37 @@ def exit_test(self, node: ast.AstNode) -> None: def exit_mod_code(self, node: ast.AstNode) -> None: """Grammar rule. + mod_code -> doc_tag KW_WITH KW_ENTRY sub_name code_block mod_code -> doc_tag KW_WITH KW_ENTRY code_block """ - node.kid = [node.kid[0], node.kid[-1]] - replace_node( - node, - ast.ModuleCode( - doc=node.kid[0], - body=node.kid[1], - parent=node.parent, - mod_link=self.mod_link, - kid=node.kid, - line=node.line, - ), - ) + if len(node.kid) == 5: + node.kid = [node.kid[0], node.kid[-2], node.kid[-1]] + replace_node( + node, + ast.ModuleCode( + doc=node.kid[0], + name=node.kid[1], + body=node.kid[2], + parent=node.parent, + mod_link=self.mod_link, + kid=node.kid, + line=node.line, + ), + ) + else: + node.kid = [node.kid[0], node.kid[-1]] + replace_node( + node, + ast.ModuleCode( + doc=node.kid[0], + name=None, + body=node.kid[1], + parent=node.parent, + mod_link=self.mod_link, + kid=node.kid, + line=node.line, + ), + ) def exit_doc_tag(self, node: ast.AstNode) -> None: """Grammar rule. diff --git a/jaclang/jac/passes/blue/blue_pygen_pass.py b/jaclang/jac/passes/blue/blue_pygen_pass.py index f8b8ec808..26cc77cbd 100644 --- a/jaclang/jac/passes/blue/blue_pygen_pass.py +++ b/jaclang/jac/passes/blue/blue_pygen_pass.py @@ -193,12 +193,20 @@ def exit_test(self, node: ast.Test) -> None: def exit_module_code(self, node: ast.ModuleCode) -> None: """Sub objects. - doc: Optional["Token"], - body: "CodeBlock", + doc: Optional[Token], + name: Optional[Name], + body: CodeBlock, + """ if node.doc: self.emit_ln(node, node.doc.value) - self.emit(node, node.body.meta["py_code"]) + if node.name: + self.emit_ln(node, f"if __name__ == '{node.name.meta['py_code']}':") + self.indent_level += 1 + self.emit(node, node.body.meta["py_code"]) + self.indent_level -= 1 + else: + self.emit(node, node.body.meta["py_code"]) def exit_import(self, node: ast.Import) -> None: """Sub objects. From 20149e0220f42750bd823d8714dfa7e62c7f3ddd Mon Sep 17 00:00:00 2001 From: marsninja Date: Sat, 16 Sep 2023 09:14:09 -0400 Subject: [PATCH 4/4] Parser out of debug mode --- jaclang/jac/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jaclang/jac/parser.py b/jaclang/jac/parser.py index 46f681fbc..173c38513 100644 --- a/jaclang/jac/parser.py +++ b/jaclang/jac/parser.py @@ -30,7 +30,7 @@ def __init__( self.ir: ast.AstNode = parse_tree_to_ast(self.ir) tokens = JacLexer.tokens - debugfile = "parser.out" + # debugfile = "parser.out" # All mighty start rule # ---------------------