diff --git a/.NET Linker.sln b/.NET Linker.sln deleted file mode 100644 index 2402748..0000000 --- a/.NET Linker.sln +++ /dev/null @@ -1,27 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EF9C24DA-47D6-42EA-BEE6-78BADDD2174C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = ".NET Linker", "src\.NET Linker\.NET Linker.csproj", "{C5790079-DC23-4ABF-8E73-72DEAC881F8D}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C5790079-DC23-4ABF-8E73-72DEAC881F8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C5790079-DC23-4ABF-8E73-72DEAC881F8D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C5790079-DC23-4ABF-8E73-72DEAC881F8D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C5790079-DC23-4ABF-8E73-72DEAC881F8D}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {C5790079-DC23-4ABF-8E73-72DEAC881F8D} = {EF9C24DA-47D6-42EA-BEE6-78BADDD2174C} - EndGlobalSection -EndGlobal diff --git a/.clang-format b/.clang-format index d161ac7..2d8645f 100644 --- a/.clang-format +++ b/.clang-format @@ -67,13 +67,14 @@ BraceWrapping: AfterClass: true AfterControlStatement: Always AfterEnum: true + AfterFunction: true AfterNamespace: true AfterStruct: true AfterExternBlock: true BeforeCatch: true BeforeElse: true BeforeLambdaBody: false - IndentBraces: true + IndentBraces: false SplitEmptyFunction: true SplitEmptyRecord: true SplitEmptyNamespace: true @@ -82,7 +83,7 @@ BreakAdjacentStringLiterals: true BreakAfterAttributes: Leave # BreakAfterReturnType: Automatic BreakBeforeBinaryOperators: None -BreakBeforeBraces: Allman +BreakBeforeBraces: Custom BreakBeforeConceptDeclarations: Allowed BreakBeforeInlineASMColon: OnlyMultiline BreakBeforeTernaryOperators: true diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 3dfaf52..338e866 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -2,12 +2,12 @@ name: Publish to GitHub on: push: - branches: ["main"] + branches: ["main", "github-action"] pull_request: branches: ["main"] jobs: - build: + build-macOS: runs-on: macos-latest steps: @@ -25,17 +25,80 @@ jobs: - name: Setup LLVM run: brew install llvm + - name: Setup Environment Variables + run: echo 'export PATH="/opt/homebrew/opt/llvm/bin:$PATH"' >> /Users/runner/.bash_profile + + - name: Setup Build Script + if: ${{ runner.os != 'Windows' }} + run: chmod +x build.sh + + - name: Build + run: | + xmake f -p macosx -a arm64 -m release + xmake -y + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: Mamba + path: | + build/macosx/arm64/release/mamba + + build-windows: + runs-on: windows-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup xmake + uses: xmake-io/github-action-setup-xmake@v1 + with: + xmake-version: latest + + - name: Build + run: | + xmake f -p windows -a x64 -m release + xmake -y + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: Mamba + path: | + build/windows/x64/release/mamba.exe + + build-linux: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup xmake + uses: xmake-io/github-action-setup-xmake@v1 + with: + xmake-version: latest + + - name: Setup Homebrew + run: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + + - name: Setup LLVM + run: brew install llvm + + - name: Setup Environment Variables + run: echo 'export PATH="/opt/homebrew/opt/llvm/bin:$PATH"' >> /Users/runner/.bash_profile + - name: Setup Build Script if: ${{ runner.os != 'Windows' }} run: chmod +x build.sh - name: Build - run: ./build.sh + run: | + xmake f -p macosx -a arm64 -m release + xmake -y - name: Upload Artifacts uses: actions/upload-artifact@v4 with: name: Mamba path: | - build/macosx/arm64/release/Jvav - build/windows/x64/release/Jvav.exe + build/macosx/arm64/release/mamba \ No newline at end of file diff --git a/.github/workflows/self-hosted.yml b/.github/workflows/self-hosted.yml new file mode 100644 index 0000000..4a69a97 --- /dev/null +++ b/.github/workflows/self-hosted.yml @@ -0,0 +1,27 @@ +name: Publish to GitHub (Self Hosted) + +on: + push: + branches: ["main", "github-action"] + pull_request: + branches: ["main"] + +jobs: + build-macOS: + runs-on: self-hosted + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Build + run: | + xmake f -p macosx -a arm64 -m release + xmake -y + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: Mamba + path: | + build/macosx/arm64/release/mamba \ No newline at end of file diff --git a/.gitignore b/.gitignore index 5200987..e842405 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,6 @@ Jvav.xcodeproj/ CMakeFiles/ CMakeScripts/ cmake_install.cmake -CMakeLists.txt CMakeCache.txt src/.NET Linker/bin diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..9ca3fdd --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 3.22) +project(mamba) + +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +if(NOT MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") +endif() + +include(FetchContent) +FetchContent_Declare( + fastio + URL https://github.com/Adttil/fast_io/archive/refs/heads/master.zip + DOWNLOAD_EXTRACT_TIMESTAMP TRUE +) +FetchContent_MakeAvailable(fastio) + +include_directories("include" "src/Mamba" "src/Mamba/Core" "src/Mamba/Code Analysis" "src/Mamba/Code Analysis/Syntax" "src/Mamba/Code Analysis/Text" "src/Mamba/Code Analysis/Binding" "src/Mamba/Code Analysis/Symbol" "src/Mamba/Code Generation") + +set(CMAKE_EXE_LINKER_FLAGS "-static") + +file(GLOB_RECURSE srcs "src/Mamba/**.cpp") +add_executable(mamba ${srcs}) +target_link_libraries(mamba PRIVATE FAST_IO) + +# LLVM Embedding +find_package(LLVM REQUIRED CONFIG) + +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +llvm_map_components_to_libnames(llvm_libs support core irreader) + +target_link_libraries(mamba PRIVATE ${llvm_libs}) + +include_directories(${LLVM_INCLUDE_DIRS}) +separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS}) +add_definitions(${LLVM_DEFINITIONS_LIST}) \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d361817 --- /dev/null +++ b/Makefile @@ -0,0 +1,208 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 3.30 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /opt/homebrew/Cellar/cmake/3.30.2/bin/cmake + +# The command to remove a file. +RM = /opt/homebrew/Cellar/cmake/3.30.2/bin/cmake -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /Users/hecker/Projects/Jvav + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /Users/hecker/Projects/Jvav + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Running CMake cache editor..." + /opt/homebrew/Cellar/cmake/3.30.2/bin/ccmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache +.PHONY : edit_cache/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Running CMake to regenerate build system..." + /opt/homebrew/Cellar/cmake/3.30.2/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache +.PHONY : rebuild_cache/fast + +# The main all target +all: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /Users/hecker/Projects/Jvav/CMakeFiles /Users/hecker/Projects/Jvav//CMakeFiles/progress.marks + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 all + $(CMAKE_COMMAND) -E cmake_progress_start /Users/hecker/Projects/Jvav/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 clean +.PHONY : clean + +# The main clean target +clean/fast: clean +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +#============================================================================= +# Target rules for targets named Mamba + +# Build rule for target. +Mamba: cmake_check_build_system + $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 Mamba +.PHONY : Mamba + +# fast build rule for target. +Mamba/fast: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Mamba.dir/build.make CMakeFiles/Mamba.dir/build +.PHONY : Mamba/fast + +src/Mamba/Mamba.o: src/Mamba/Mamba.cpp.o +.PHONY : src/Mamba/Mamba.o + +# target to build an object file +src/Mamba/Mamba.cpp.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Mamba.dir/build.make CMakeFiles/Mamba.dir/src/Mamba/Mamba.cpp.o +.PHONY : src/Mamba/Mamba.cpp.o + +src/Mamba/Mamba.i: src/Mamba/Mamba.cpp.i +.PHONY : src/Mamba/Mamba.i + +# target to preprocess a source file +src/Mamba/Mamba.cpp.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Mamba.dir/build.make CMakeFiles/Mamba.dir/src/Mamba/Mamba.cpp.i +.PHONY : src/Mamba/Mamba.cpp.i + +src/Mamba/Mamba.s: src/Mamba/Mamba.cpp.s +.PHONY : src/Mamba/Mamba.s + +# target to generate assembly for a file +src/Mamba/Mamba.cpp.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Mamba.dir/build.make CMakeFiles/Mamba.dir/src/Mamba/Mamba.cpp.s +.PHONY : src/Mamba/Mamba.cpp.s + +src/Mamba/main.o: src/Mamba/main.cpp.o +.PHONY : src/Mamba/main.o + +# target to build an object file +src/Mamba/main.cpp.o: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Mamba.dir/build.make CMakeFiles/Mamba.dir/src/Mamba/main.cpp.o +.PHONY : src/Mamba/main.cpp.o + +src/Mamba/main.i: src/Mamba/main.cpp.i +.PHONY : src/Mamba/main.i + +# target to preprocess a source file +src/Mamba/main.cpp.i: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Mamba.dir/build.make CMakeFiles/Mamba.dir/src/Mamba/main.cpp.i +.PHONY : src/Mamba/main.cpp.i + +src/Mamba/main.s: src/Mamba/main.cpp.s +.PHONY : src/Mamba/main.s + +# target to generate assembly for a file +src/Mamba/main.cpp.s: + $(MAKE) $(MAKESILENT) -f CMakeFiles/Mamba.dir/build.make CMakeFiles/Mamba.dir/src/Mamba/main.cpp.s +.PHONY : src/Mamba/main.cpp.s + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... edit_cache" + @echo "... rebuild_cache" + @echo "... Mamba" + @echo "... src/Mamba/Mamba.o" + @echo "... src/Mamba/Mamba.i" + @echo "... src/Mamba/Mamba.s" + @echo "... src/Mamba/main.o" + @echo "... src/Mamba/main.i" + @echo "... src/Mamba/main.s" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/docs/draft/Jvav 24.pdf b/docs/draft/Jvav 24.pdf index fe43b29..52970d1 100644 Binary files a/docs/draft/Jvav 24.pdf and b/docs/draft/Jvav 24.pdf differ diff --git a/docs/draft/Jvav 24.typ b/docs/draft/Jvav 24.typ index 220fcee..57f7858 100644 --- a/docs/draft/Jvav 24.typ +++ b/docs/draft/Jvav 24.typ @@ -1,31 +1,112 @@ +#set text(font: "PT Sans") #set heading(numbering: "1.") +#set page(footer: context [ + #h(1fr) + #counter(page).display( + "1" + ) +]) #let keyword-color = eastern #let since-color = green #let user-color = blue #let bracket-color = orange -#align(center, text(17pt)[ - Jvav 24 Release +#align(center, text(24pt)[ + Working Draft, Standard for Programming Language Jvav ]) -#align(center, [ - _Released July 2024 _ -]) +#table( + columns: 2, + stroke: none +)[#text(12pt)[Date:]][#text(12pt)[2024-8-20] +][#text(12pt)[Reply-to:]][#text(12pt)[heckerpowered (#text(12pt, user-color)[heckerpowered\@icloud.com])]] + +#align(bottom)[ + This is an early release of Jvav, many if the details are have yet to be finalized, so this is just an introduction to the syntax +] + +#pagebreak() + +#show outline.entry.where( + level: 1 +): it => { + v(12pt, weak: true) + strong(it) +} +#outline( + indent: auto +) + +#pagebreak() + += Basics +== Preamble + +An _#text(user-color)[entity]_ is a _#text(user-color)[value]_, _#text(user-color)[object]_, _#text(user-color)[function]_, _#text(user-color)[class member]_. + +A name is a _#text(user-color)[identifier]_. + +Every name is introduced by a *declaration*, which is a +- _#text(user-color)[function-declaration]_ (#text(user-color)[@declaration.function]) +- _#text(user-color)[parameter-declaration]_ (#text(user-color)[@declaration.function.parameter]) +- _#text(user-color)[variable-declaration]_ (#text(user-color)[@declaration.variable]) -Jvav 24 is the first major Jvav Release, supports a few syntaxes and features. The versions of Jvav are named by year, e.g. a Jvav version released in 2024 should be called Jvav 24. +== Compilation unit -This is an early release of Jvav, many if the details are have yet to be finalized, so this is just an introduction to the syntax +A compilation unit is the smallest unit of code that can be compiled individually. -= Compilation unit +Each compilation unit has a _#text(user-color)[global scope]_, which contains the entire compilation unit. -In general, a Jvav source file corresponds to a _compilation unit_, and a _compilation unit_ contains several members. +== Phases of compilation -Members are: -- Function declaration #emph(text(since-color)[(since Jvav 24)]) -- Global statement #emph(text(since-color)[(since Jvav 24)]) +Jvav source files are processed by the compiler to produce Jvav programs. -_Global statement_ are any valid statement #emph(text(since-color)[(since Jvav 24)]) +=== Lexical analysis + +Parsing a Jvav source file into a collection of tokens using a lexical analyzer (a.k.a. lexer). + +==== Tokens + +Token is the smallest meaningful element in a compilation unit + +Tokens are: +- _#text(user-color)[identifiers]_ +- _#text(user-color)[keywords]_ +- _#text(user-color)[literals]_ +- _#text(user-color)[operators and punctuators]_ + +If any part of the source code cannot be parsed into any of the above tokens, then the part is considered to be an invalid character and the program is ill-formed. + +=== Syntactic Analysis + +Syntactic analysis is also known as parser. The collection of tokens is not yet semantic.Parser parses the collection of tokens into meaningful combinations. They are usually expressions or statements. + +#table( + columns: 4, + stroke: none, + align: (right, center, left, right) +)[Assignment expression syntax][-][_#text(user-color)[identifier]_ _#text(user-color)[equal]_ _#text(user-color)[expression]_ +][(1)][Binary expression syntax][-][_#text(user-color)[expression]_ _#text(user-color)[operator-token]_][(2) +][Block statement syntax][-][_#text(user-color)[open-brace-token]_ _#text(user-color)[statements]_ _#text(user-color)[close-brace-token]_][(3) +][Break statement syntax][-][_#text(user-color)[break-keyword]_][(4) +][Continue statement syntax][-][_#text(user-color)[continue-keyword]_][(5) +][Call expression syntax][-][_#text(user-color)[identifier]_ _#text(user-color)[open-parenthesis-token]_ _#text(user-color)[argument-list]_ _#text(user-color)[close-parenthesis-token]_][(6) +][Do-while statement syntax][-][_#text(user-color)[do-keyword]_ _#text(user-color)[statements]_ _#text(user-color)[while-keyword]_ _#text(user-color)[expression]_][(7) +][Else clause syntax][-][_#text(user-color)[else-keyword]_ _#text(user-color)[else-statements]_][(8) +][Expression statement syntax][-][_#text(user-color)[expression]_][(9) +][For statement syntax][-][_#text(user-color)[for-keyword]_ _#text(user-color)[open-parenthesis-token]_ _#text(user-color)[init-statement]_ _#text(user-color)[colon-token]_ _#text(user-color)[condition-expression]_ _#text(user-color)[colon-token]_ _#text(user-color)[expression]_ _#text(user-color)[close-parenthesis-token]_][(10) +][Function declaration syntax][-][_#text(user-color)[function-keyword]_ _#text(user-color)[identifier]_ _#text(user-color)[open-parenthesis-token]_ _#text(user-color)[parameter-list]_ _#text(user-color)[close-parenthesis-token]_ _#text(user-color)[type-clause]_ _#text(user-color)[statements]_][(11) +][Name expression][-][_#text(user-color)[identifier]_][(12) +][Parameter syntax][-][_#text(user-color)[identifier]_ _#text(user-color)[type-clause]_][(13) +][Parenthesized expression syntax][-][_#text(user-color)[open-parenthesis-token]_ _#text(user-color)[expression]_ _#text(user-color)[close-parenthesis-token]_][(14) +][Return statement syntax][-][_#text(user-color)[return-keyword]_][(15) +][Type clause syntax][-][_#text(user-color)[colon-token]_ _#text(user-color)[identifier]_][(16) +][Unary expression syntax][-][_#text(user-color)[operator-token]_ _#text(user-color)[expression]_][(17) +][Variable declaration syntax][-][_#text(user-color)[keyword]_ _#text(user-color)[identifier]_ _#text(user-color)[type-clause]#sub[optional]_ _#text(user-color)[condition-expression]_ _#text(user-color)[equals-token]_ _#text(user-color)[initializer]_][(18) +][While statement syntax][-][_#text(user-color)[while-keyword]_ _#text(user-color)[expression]_ _#text(user-color)[statements]_][(19)] + +#pagebreak() = Scope @@ -34,19 +115,6 @@ In a Jvav source file, the outermost scope are called _global scope_. When we de A _local scope_ can be created by surrounding statements with curly bracket syntax. -[Example -` -Complation unit #1: - -... - -// global scope -{ // local scope - ... -} -` --- _end example_] - == Block scope The following syntaxes introduces a _block scope_ that includes statements: @@ -150,7 +218,7 @@ A name expression holds an identifier that refers to function, variable or a con Postfix expressions group left-to-right. -==== Call expression +==== Call expression A call expression is a postfix expression followed by parentheses containing a possibly empty, comma-separated list of expressions which constitute the arguments to the function. @@ -295,7 +363,7 @@ A variable declaration is a statement that introduces and optionally initialize If the _#text(user-color)[type-clause]_ is empty, then the type of the variable is deduced from the initializer. -== Function declaration +== Function declaration A function declaration declares a function in current scope and associates the function's name, parameters and return type. @@ -319,8 +387,8 @@ A function declaration declares a function in current scope and associates the f The parameters of the function are in the same scope of the _#text(user-color)[statement]_ -=== Parameter syntax +=== Parameter syntax Parameter syntax declares a parameter of a function. -_#text(user-color)[parameter-name] _:_ #text(user-color)[type-clause]_ \ No newline at end of file +_#text(user-color)[parameter-name] _:_ #text(user-color)[type-clause]_ diff --git a/src/.NET Linker/.NET Linker.csproj b/src/.NET Linker/.NET Linker.csproj deleted file mode 100644 index 89b90f1..0000000 --- a/src/.NET Linker/.NET Linker.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - Exe - net8.0 - Jvav - enable - enable - true - - - - - - - diff --git a/src/.NET Linker/Linker/LinkingReader.cs b/src/.NET Linker/Linker/LinkingReader.cs deleted file mode 100644 index d62cb31..0000000 --- a/src/.NET Linker/Linker/LinkingReader.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Text; - -namespace Jvav.Linker; - -public class LinkingReader(Stream inputStream) -{ - private readonly BinaryReader reader = new(inputStream); - public Stream InputStream { get; } = inputStream; - - public ulong ReadLinkerVersion() - { - return reader.ReadUInt64(); - } - - public V1.Linking LinkV1() - { - return new V1.Linking(InputStream); - } -} diff --git a/src/.NET Linker/Linker/V1/Identifier.cs b/src/.NET Linker/Linker/V1/Identifier.cs deleted file mode 100644 index 96c24d0..0000000 --- a/src/.NET Linker/Linker/V1/Identifier.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Jvav.Linker.V1; - -enum Identifier : byte -{ - Function, - Variable, - Type, - Instruction, - String -} \ No newline at end of file diff --git a/src/.NET Linker/Linker/V1/InternalOpCodes.cs b/src/.NET Linker/Linker/V1/InternalOpCodes.cs deleted file mode 100644 index d20e452..0000000 --- a/src/.NET Linker/Linker/V1/InternalOpCodes.cs +++ /dev/null @@ -1,223 +0,0 @@ -namespace Jvav.Linker.V1; - -enum InternalOpCodes -{ - Add = 0x58, - AddOvf = 0xD6, - AddOvfUn = 0xD7, - And = 0x5F, - Arglist = 0xFE00, - Beq = 0x3B, - BeqS = 0x2E, - Bge = 0x3C, - BgeS = 0x2F, - BgeUn = 0x41, - BgeUnS = 0x34, - Bgt = 0x3D, - BgtS = 0x30, - BgtUn = 0x42, - BgtUnS = 0x35, - Ble = 0x3E, - BleS = 0x31, - BleUn = 0x43, - BleUnS = 0x36, - Blt = 0x3F, - BltS = 0x32, - BltUn = 0x44, - BltUnS = 0x37, - BneUn = 0x40, - BneUnS = 0x33, - Box = 0x8C, - Br = 0x38, - BrS = 0x2B, - Break = 0x01, - Brfalse = 0x39, - BrfalseS = 0x2C, - Brtrue = 0x3A, - BrtrueS = 0x2D, - Call = 0x28, - Calli = 0x29, - Callvirt = 0x6F, - Castclass = 0x74, - Ceq = 0xFF01, - Cgt = 0xFE02, - CgtUn = 0xFE03, - Ckfinite = 0xC3, - Clt = 0xFE04, - CltUn = 0xFE05, - Constrained = 0xFF16, - ConvI = 0xD3, - ConvI1 = 0x67, - ConvI2 = 0x68, - ConvI4 = 0x69, - ConvI8 = 0x6A, - ConvOvfI = 0xD4, - ConvOvfIUn = 0x8A, - ConvOvfI1 = 0xB3, - ConvOvfI1Un = 0x82, - ConvOvfI2 = 0xB5, - ConvOvfI2Un = 0x83, - ConvOvfI4 = 0xB7, - ConvOvfI4Un = 0x84, - ConvOvfI8 = 0xB9, - ConvOvfI8Un = 0x85, - ConvOvfU = 0xD5, - ConvOvfUUn = 0x8B, - ConvOvfU1 = 0xB4, - ConvOvfU1Un = 0x86, - ConvOvfU2 = 0xB6, - ConvOvfU2Un = 0x87, - ConvOvfU4 = 0xB8, - ConvOvfu4Un = 0x88, - ConvOvfU8 = 0xBA, - ConvOvfU8Un = 0x89, - ConvRUn = 0x76, - ConvR4 = 0x6B, - ConvR8 = 0x6C, - ConvU = 0xE0, - ConvU1 = 0xD2, - ConvU2 = 0xD1, - ConvU4 = 0x6D, - ConvU8 = 0x6E, - Cpblk = 0xFE17, - Cpobj = 0x70, - Div = 0x5B, - DivUn = 0x5C, - Dup = 0x25, - Endfilter = 0xFE11, - Endfinally = 0xDC, - Initblk = 0xFE18, - Initobj = 0xFE15, - Isinst = 0x75, - jmp = 0x27, - Ldarg = 0xFE09, - Ldarg0 = 0x02, - Ldarg1 = 0x03, - Ldarg2 = 0x04, - Ldarg3 = 0x05, - LdargS = 0x0E, - Ldarga = 0xFE0A, - LdargaS = 0x0F, - LdcI4 = 0x20, - LcdI40 = 0x16, - LdcI41 = 0x17, - LdcI42 = 0x18, - LdcI43 = 0x19, - LdcI44 = 0x1A, - LdcI45 = 0x1B, - LdcI46 = 0x1C, - LdcI47 = 0x1D, - LdcI48 = 0x1E, - LdcI4M1 = 0x15, - LdcI4S = 0x1F, - LdcI8 = 0x21, - LdcR4 = 0x22, - LdcR8 = 0x23, - Ldelem = 0xA3, - LdelemI = 0x97, - LdelemI1 = 0x90, - LdelemI2 = 0x92, - LdelemI4 = 0x94, - LdelemI8 = 0x96, - LdelemR4 = 0x98, - LdelemR8 = 0x99, - LdelemRef = 0x9A, - LdelemU1 = 0x91, - LdelemU2 = 0x93, - LdelemU4 = 0x95, - Ldelema = 0x8F, - Ldfld = 0x7B, - Ldflda = 0x7C, - Ldftn = 0xFF06, - LdindI = 0x4D, - LdindI1 = 0x46, - LdindI2 = 0x48, - LdindI4 = 0x4A, - LdindI8 = 0x4C, - LdindR4 = 0x4E, - LdindR8 = 0x4F, - LdindRef = 0x50, - LdindU1 = 0x47, - LdindU2 = 0x49, - LdindU4 = 0x4B, - Ldlen = 0x8E, - Ldloc = 0xFE0C, - Ldloc0 = 0x06, - Ldloc1 = 0x07, - Ldloc2 = 0x08, - Ldloc3 = 0x09, - LdlocS = 0x11, - Ldloca = 0xFE0D, - LdlocaS = 0x12, - Ldnull = 0x14, - Ldobj = 0x71, - Ldsfld = 0x7E, - Ldsflda = 0x7F, - Ldstr = 0x72, - Ldtoken = 0xD0, - Ldvirtftn = 0xFF07, - Leave = 0xDD, - LeaveS = 0xDE, - Localloc = 0xFE0F, - Mkrefany = 0xC6, - Mul = 0x5A, - MulOvf = 0xD8, - MulOvfUn = 0xD9, - Neg = 0x65, - Newarr = 0x8D, - Newobj = 0x73, - Nop = 0x00, - Not = 0x66, - Or = 0x60, - Pop = 0x26, - Readonly = 0xFE1E, - Refanytype = 0xFF1D, - Refanyval = 0xC2, - Rem = 0x5D, - RemUn = 0x5E, - Ret = 0x2A, - Rethrow = 0xFF1A, - Shl = 0x62, - Shr = 0x63, - ShrUn = 0x64, - Sizeof = 0xFE1C, - Starg = 0xFE0B, - StargS = 0x10, - Stelem = 0xA4, - StelemI = 0x9B, - StelemI1 = 0x9C, - StelemI2 = 0x9D, - StelemI4 = 0x9E, - StelemI8 = 0x9F, - StelemR4 = 0xA0, - StelemR8 = 0xA1, - StelemRef = 0xA2, - Stfld = 0x7D, - StindI = 0xDF, - StindI1 = 0x52, - StintI2 = 0x53, - StindI4 = 0x54, - StindI8 = 0x55, - StindR4 = 0x56, - StintR8 = 0x57, - StindRef = 0x51, - Stloc = 0xFF0E, - Stloc0 = 0x0A, - Stloc1 = 0x0B, - Stloc2 = 0x0C, - Stloc3 = 0x0D, - StlocS = 0x13, - Stobj = 0x81, - Stsfld = 0x80, - Sub = 0x59, - SubOvf = 0xDA, - SubOvfUn = 0xDB, - Switch = 0x45, - Tailcall = 0xFF14, - Throw = 0x7A, - Unaligned = 0xFE12, - Unbox = 0x79, - UnboxAny = 0xA5, - Volatile = 0xFE13, - Xor = 0x61, -}; \ No newline at end of file diff --git a/src/.NET Linker/Linker/V1/LinkerV1.cs b/src/.NET Linker/Linker/V1/LinkerV1.cs deleted file mode 100644 index 7cfb1e2..0000000 --- a/src/.NET Linker/Linker/V1/LinkerV1.cs +++ /dev/null @@ -1,452 +0,0 @@ -using System.Reflection.Emit; -using System.Text; -using Mono.Cecil; -using Mono.Cecil.Cil; - -using OpCodes = Mono.Cecil.Cil.OpCodes; -using OpCode = Mono.Cecil.Cil.OpCode; -using System.Reflection; -using TypeAttributes = Mono.Cecil.TypeAttributes; -using MethodAttributes = Mono.Cecil.MethodAttributes; - -namespace Jvav.Linker.V1; - -public class Linking -{ - private readonly BinaryReader reader; - private readonly AssemblyDefinition assembly; - private readonly TypeDefinition programType; - - private readonly List references = []; - private readonly MethodReference printlnMethod; - private readonly AssemblyDefinition mscorlib; - public Linking(Stream inputStream) - { - reader = new(inputStream); - ModuleName = ReadModuleName(); - - mscorlib = AssemblyDefinition.ReadAssembly("mscorlib.dll"); - references.Add(mscorlib); - - var assemblyName = new AssemblyNameDefinition(ModuleName, new Version(1, 0, 0, 0)); - assembly = AssemblyDefinition.CreateAssembly(assemblyName, ModuleName, ModuleKind.Console); - - var objectType = ResolveType("System.Object")!; - programType = new TypeDefinition("", "Program", TypeAttributes.Abstract | TypeAttributes.Sealed, objectType); - assembly.MainModule.Types.Add(programType); - - printlnMethod = ResolveMethod("System.Console", "WriteLine", ["System.Object"])!; - - try - { - ReadMembers(); - } - catch (EndOfStreamException) { }; - } - - public string ModuleName { get; private set; } - - private MethodReference? ResolveMethod(string typeName, string methodName, string[] parameterTypeNames) - { - var foundTypes = references - .SelectMany(a => a.Modules) - .SelectMany(m => m.Types) - .Where(t => t.FullName == typeName) - .ToArray(); - if (foundTypes.Length != 1) - { - return null; - } - - var foundType = foundTypes.First(); - var methods = foundType.Methods.Where(method => method.Name == methodName); - - foreach (var method in methods) - { - if (method.Parameters.Count != parameterTypeNames.Length) - { - continue; - } - - var allParametersMatch = true; - - for (var i = 0; i < parameterTypeNames.Length; i++) - { - if (method.Parameters[i].ParameterType.FullName != parameterTypeNames[i]) - { - allParametersMatch = false; - break; - } - } - - if (!allParametersMatch) - { - continue; - } - - return assembly.MainModule.Import(method); - } - - return null; - } - - TypeReference? ResolveType(string metadataName) - { - var foundTypes = references.SelectMany(a => a.Modules) - .SelectMany(m => m.Types) - .Where(t => t.FullName == metadataName) - .ToArray(); - if (foundTypes.Length == 1) - { - var typeReference = assembly.MainModule.Import(foundTypes.First()); - return typeReference; - } - - return null; - } - - private string ReadModuleName() - { - var moduleNameLength = reader.ReadUInt64(); - var bytes = reader.ReadBytes((int)moduleNameLength); - var moduleName = Encoding.UTF8.GetString(bytes); - return moduleName; - } - - private Identifier ReadMemberType() - { - var memberType = (Identifier)reader.ReadByte(); - return memberType; - } - - private void ReadMembers() - { - while (true) - { - var memberType = ReadMemberType(); - switch (memberType) - { - case Identifier.Function: - ReadFunction(); - break; - default: - Console.WriteLine($"Unknown member type: {memberType}"); - return; - } - } - } - - private Identifier ReadIdentifier() - { - var identifier = (Identifier)reader.ReadByte(); - return identifier; - } - - private OpCode ReadOpCode() - { - var opCode = (InternalOpCodes)reader.ReadInt32(); - return opCode switch - { - InternalOpCodes.Add => OpCodes.Add, - InternalOpCodes.AddOvf => OpCodes.Add_Ovf, - InternalOpCodes.AddOvfUn => OpCodes.Add_Ovf_Un, - InternalOpCodes.And => OpCodes.And, - InternalOpCodes.Arglist => OpCodes.Arglist, - InternalOpCodes.Beq => OpCodes.Beq, - InternalOpCodes.BeqS => OpCodes.Beq_S, - InternalOpCodes.Bge => OpCodes.Bge, - InternalOpCodes.BgeS => OpCodes.Bge_S, - InternalOpCodes.BgeUn => OpCodes.Bge_Un, - InternalOpCodes.BgeUnS => OpCodes.Bge_Un_S, - InternalOpCodes.Bgt => OpCodes.Bgt, - InternalOpCodes.BgtS => OpCodes.Bgt_S, - InternalOpCodes.BgtUn => OpCodes.Bgt_Un, - InternalOpCodes.BgtUnS => OpCodes.Bgt_Un_S, - InternalOpCodes.Ble => OpCodes.Ble, - InternalOpCodes.BleS => OpCodes.Ble_S, - InternalOpCodes.BleUn => OpCodes.Ble_Un, - InternalOpCodes.BleUnS => OpCodes.Ble_Un_S, - InternalOpCodes.Blt => OpCodes.Blt, - InternalOpCodes.BltS => OpCodes.Blt_S, - InternalOpCodes.BltUn => OpCodes.Blt_Un, - InternalOpCodes.BltUnS => OpCodes.Blt_Un_S, - InternalOpCodes.BneUn => OpCodes.Bne_Un, - InternalOpCodes.BneUnS => OpCodes.Bne_Un_S, - InternalOpCodes.Box => OpCodes.Box, - InternalOpCodes.Br => OpCodes.Br, - InternalOpCodes.BrS => OpCodes.Br_S, - InternalOpCodes.Break => OpCodes.Break, - InternalOpCodes.Brfalse => OpCodes.Brfalse, - InternalOpCodes.BrfalseS => OpCodes.Brfalse_S, - InternalOpCodes.Brtrue => OpCodes.Brtrue, - InternalOpCodes.BrtrueS => OpCodes.Brtrue_S, - InternalOpCodes.Call => OpCodes.Call, - InternalOpCodes.Calli => OpCodes.Calli, - InternalOpCodes.Callvirt => OpCodes.Callvirt, - InternalOpCodes.Castclass => OpCodes.Castclass, - InternalOpCodes.Ceq => OpCodes.Ceq, - InternalOpCodes.Cgt => OpCodes.Cgt, - InternalOpCodes.CgtUn => OpCodes.Cgt_Un, - InternalOpCodes.Ckfinite => OpCodes.Ckfinite, - InternalOpCodes.Clt => OpCodes.Clt, - InternalOpCodes.CltUn => OpCodes.Clt_Un, - InternalOpCodes.Constrained => OpCodes.Constrained, - InternalOpCodes.ConvI => OpCodes.Conv_I, - InternalOpCodes.ConvI1 => OpCodes.Conv_I1, - InternalOpCodes.ConvI2 => OpCodes.Conv_I2, - InternalOpCodes.ConvI4 => OpCodes.Conv_I4, - InternalOpCodes.ConvI8 => OpCodes.Conv_I8, - InternalOpCodes.ConvOvfI => OpCodes.Conv_Ovf_I, - InternalOpCodes.ConvOvfIUn => OpCodes.Conv_Ovf_I_Un, - InternalOpCodes.ConvOvfI1 => OpCodes.Conv_Ovf_I1, - InternalOpCodes.ConvOvfI1Un => OpCodes.Conv_Ovf_I1_Un, - InternalOpCodes.ConvOvfI2 => OpCodes.Conv_Ovf_I2, - InternalOpCodes.ConvOvfI2Un => OpCodes.Conv_Ovf_I2_Un, - InternalOpCodes.ConvOvfI4 => OpCodes.Conv_Ovf_I4, - InternalOpCodes.ConvOvfI4Un => OpCodes.Conv_Ovf_I4_Un, - InternalOpCodes.ConvOvfI8 => OpCodes.Conv_Ovf_I8, - InternalOpCodes.ConvOvfI8Un => OpCodes.Conv_Ovf_I8_Un, - InternalOpCodes.ConvOvfU => OpCodes.Conv_Ovf_U, - InternalOpCodes.ConvOvfUUn => OpCodes.Conv_Ovf_U_Un, - InternalOpCodes.ConvOvfU1 => OpCodes.Conv_Ovf_U1, - InternalOpCodes.ConvOvfU1Un => OpCodes.Conv_Ovf_U1_Un, - InternalOpCodes.ConvOvfU2 => OpCodes.Conv_Ovf_U2, - InternalOpCodes.ConvOvfU2Un => OpCodes.Conv_Ovf_U2_Un, - InternalOpCodes.ConvOvfU4 => OpCodes.Conv_Ovf_U4, - InternalOpCodes.ConvOvfu4Un => OpCodes.Conv_Ovf_U4_Un, - InternalOpCodes.ConvOvfU8 => OpCodes.Conv_Ovf_U8, - InternalOpCodes.ConvOvfU8Un => OpCodes.Conv_Ovf_U8_Un, - InternalOpCodes.ConvRUn => OpCodes.Conv_R_Un, - InternalOpCodes.ConvR4 => OpCodes.Conv_R4, - InternalOpCodes.ConvR8 => OpCodes.Conv_R8, - InternalOpCodes.ConvU => OpCodes.Conv_U, - InternalOpCodes.ConvU1 => OpCodes.Conv_U1, - InternalOpCodes.ConvU2 => OpCodes.Conv_U2, - InternalOpCodes.ConvU4 => OpCodes.Conv_U4, - InternalOpCodes.ConvU8 => OpCodes.Conv_U8, - InternalOpCodes.Cpblk => OpCodes.Cpblk, - InternalOpCodes.Cpobj => OpCodes.Cpobj, - InternalOpCodes.Div => OpCodes.Div, - InternalOpCodes.DivUn => OpCodes.Div_Un, - InternalOpCodes.Dup => OpCodes.Dup, - InternalOpCodes.Endfilter => OpCodes.Endfilter, - InternalOpCodes.Endfinally => OpCodes.Endfinally, - InternalOpCodes.Initblk => OpCodes.Initblk, - InternalOpCodes.Initobj => OpCodes.Initobj, - InternalOpCodes.Isinst => OpCodes.Isinst, - InternalOpCodes.jmp => OpCodes.Jmp, - InternalOpCodes.Ldarg => OpCodes.Ldarg, - InternalOpCodes.Ldarg0 => OpCodes.Ldarg_0, - InternalOpCodes.Ldarg1 => OpCodes.Ldarg_1, - InternalOpCodes.Ldarg2 => OpCodes.Ldarg_2, - InternalOpCodes.Ldarg3 => OpCodes.Ldarg_3, - InternalOpCodes.LdargS => OpCodes.Ldarg_S, - InternalOpCodes.Ldarga => OpCodes.Ldarga, - InternalOpCodes.LdargaS => OpCodes.Ldarga_S, - InternalOpCodes.LdcI4 => OpCodes.Ldc_I4, - InternalOpCodes.LcdI40 => OpCodes.Ldc_I4_0, - InternalOpCodes.LdcI41 => OpCodes.Ldc_I4_1, - InternalOpCodes.LdcI42 => OpCodes.Ldc_I4_2, - InternalOpCodes.LdcI43 => OpCodes.Ldc_I4_3, - InternalOpCodes.LdcI44 => OpCodes.Ldc_I4_4, - InternalOpCodes.LdcI45 => OpCodes.Ldc_I4_5, - InternalOpCodes.LdcI46 => OpCodes.Ldc_I4_6, - InternalOpCodes.LdcI47 => OpCodes.Ldc_I4_7, - InternalOpCodes.LdcI48 => OpCodes.Ldc_I4_8, - InternalOpCodes.LdcI4M1 => OpCodes.Ldc_I4_M1, - InternalOpCodes.LdcI4S => OpCodes.Ldc_I4_S, - InternalOpCodes.LdcI8 => OpCodes.Ldc_I8, - InternalOpCodes.LdcR4 => OpCodes.Ldc_R4, - InternalOpCodes.LdcR8 => OpCodes.Ldc_R8, - InternalOpCodes.Ldelem => OpCodes.Ldelem_Any, - InternalOpCodes.LdelemI => OpCodes.Ldelem_I, - InternalOpCodes.LdelemI1 => OpCodes.Ldelem_I1, - InternalOpCodes.LdelemI2 => OpCodes.Ldelem_I2, - InternalOpCodes.LdelemI4 => OpCodes.Ldelem_I4, - InternalOpCodes.LdelemI8 => OpCodes.Ldelem_I8, - InternalOpCodes.LdelemR4 => OpCodes.Ldelem_R4, - InternalOpCodes.LdelemR8 => OpCodes.Ldelem_R8, - InternalOpCodes.LdelemRef => OpCodes.Ldelem_Ref, - InternalOpCodes.LdelemU1 => OpCodes.Ldelem_U1, - InternalOpCodes.LdelemU2 => OpCodes.Ldelem_U2, - InternalOpCodes.LdelemU4 => OpCodes.Ldelem_U4, - InternalOpCodes.Ldelema => OpCodes.Ldelema, - InternalOpCodes.Ldfld => OpCodes.Ldfld, - InternalOpCodes.Ldflda => OpCodes.Ldflda, - InternalOpCodes.Ldftn => OpCodes.Ldftn, - InternalOpCodes.LdindI => OpCodes.Ldind_I, - InternalOpCodes.LdindI1 => OpCodes.Ldind_I1, - InternalOpCodes.LdindI2 => OpCodes.Ldind_I2, - InternalOpCodes.LdindI4 => OpCodes.Ldind_I4, - InternalOpCodes.LdindI8 => OpCodes.Ldind_I8, - InternalOpCodes.LdindR4 => OpCodes.Ldind_R4, - InternalOpCodes.LdindR8 => OpCodes.Ldind_R8, - InternalOpCodes.LdindRef => OpCodes.Ldind_Ref, - InternalOpCodes.LdindU1 => OpCodes.Ldind_U1, - InternalOpCodes.LdindU2 => OpCodes.Ldind_U2, - InternalOpCodes.LdindU4 => OpCodes.Ldind_U4, - InternalOpCodes.Ldlen => OpCodes.Ldlen, - InternalOpCodes.Ldloc => OpCodes.Ldloc, - InternalOpCodes.Ldloc0 => OpCodes.Ldloc_0, - InternalOpCodes.Ldloc1 => OpCodes.Ldloc_1, - InternalOpCodes.Ldloc2 => OpCodes.Ldloc_2, - InternalOpCodes.Ldloc3 => OpCodes.Ldloc_3, - InternalOpCodes.LdlocS => OpCodes.Ldloc_S, - InternalOpCodes.Ldloca => OpCodes.Ldloca, - InternalOpCodes.LdlocaS => OpCodes.Ldloca_S, - InternalOpCodes.Ldnull => OpCodes.Ldnull, - InternalOpCodes.Ldobj => OpCodes.Ldobj, - InternalOpCodes.Ldsfld => OpCodes.Ldsfld, - InternalOpCodes.Ldsflda => OpCodes.Ldsflda, - InternalOpCodes.Ldstr => OpCodes.Ldstr, - InternalOpCodes.Ldtoken => OpCodes.Ldtoken, - InternalOpCodes.Ldvirtftn => OpCodes.Ldvirtftn, - InternalOpCodes.Leave => OpCodes.Leave, - InternalOpCodes.LeaveS => OpCodes.Leave_S, - InternalOpCodes.Localloc => OpCodes.Localloc, - InternalOpCodes.Mkrefany => OpCodes.Mkrefany, - InternalOpCodes.Mul => OpCodes.Mul, - InternalOpCodes.MulOvf => OpCodes.Mul_Ovf, - InternalOpCodes.MulOvfUn => OpCodes.Mul_Ovf_Un, - InternalOpCodes.Neg => OpCodes.Neg, - InternalOpCodes.Newarr => OpCodes.Newarr, - InternalOpCodes.Newobj => OpCodes.Newobj, - InternalOpCodes.Nop => OpCodes.Nop, - InternalOpCodes.Not => OpCodes.Not, - InternalOpCodes.Or => OpCodes.Or, - InternalOpCodes.Pop => OpCodes.Pop, - InternalOpCodes.Readonly => OpCodes.Readonly, - InternalOpCodes.Refanytype => OpCodes.Refanytype, - InternalOpCodes.Refanyval => OpCodes.Refanyval, - InternalOpCodes.Rem => OpCodes.Rem, - InternalOpCodes.RemUn => OpCodes.Rem_Un, - InternalOpCodes.Ret => OpCodes.Ret, - InternalOpCodes.Rethrow => OpCodes.Rethrow, - InternalOpCodes.Shl => OpCodes.Shl, - InternalOpCodes.Shr => OpCodes.Shr, - InternalOpCodes.ShrUn => OpCodes.Shr_Un, - InternalOpCodes.Sizeof => OpCodes.Sizeof, - InternalOpCodes.Starg => OpCodes.Starg, - InternalOpCodes.StargS => OpCodes.Starg_S, - InternalOpCodes.Stelem => OpCodes.Stelem_Any, - InternalOpCodes.StelemI => OpCodes.Stelem_I, - InternalOpCodes.StelemI1 => OpCodes.Stelem_I1, - InternalOpCodes.StelemI2 => OpCodes.Stelem_I2, - InternalOpCodes.StelemI4 => OpCodes.Stelem_I4, - InternalOpCodes.StelemI8 => OpCodes.Stelem_I8, - InternalOpCodes.StelemR4 => OpCodes.Stelem_R4, - InternalOpCodes.StelemR8 => OpCodes.Stelem_R8, - InternalOpCodes.StelemRef => OpCodes.Stelem_Ref, - InternalOpCodes.Stfld => OpCodes.Stfld, - InternalOpCodes.StindI => OpCodes.Stind_I, - InternalOpCodes.StindI1 => OpCodes.Stind_I1, - InternalOpCodes.StintI2 => OpCodes.Stind_I2, - InternalOpCodes.StindI4 => OpCodes.Stind_I4, - InternalOpCodes.StindI8 => OpCodes.Stind_I8, - InternalOpCodes.StindR4 => OpCodes.Stind_R4, - InternalOpCodes.StintR8 => OpCodes.Stind_R8, - InternalOpCodes.StindRef => OpCodes.Stind_Ref, - InternalOpCodes.Stloc => OpCodes.Stloc, - InternalOpCodes.Stloc0 => OpCodes.Stloc_0, - InternalOpCodes.Stloc1 => OpCodes.Stloc_1, - InternalOpCodes.Stloc2 => OpCodes.Stloc_2, - InternalOpCodes.Stloc3 => OpCodes.Stloc_3, - InternalOpCodes.StlocS => OpCodes.Stloc_S, - InternalOpCodes.Stobj => OpCodes.Stobj, - InternalOpCodes.Stsfld => OpCodes.Stsfld, - InternalOpCodes.Sub => OpCodes.Sub, - InternalOpCodes.SubOvf => OpCodes.Sub_Ovf, - InternalOpCodes.SubOvfUn => OpCodes.Sub_Ovf_Un, - InternalOpCodes.Switch => OpCodes.Switch, - InternalOpCodes.Tailcall => OpCodes.Tail, - InternalOpCodes.Throw => OpCodes.Throw, - InternalOpCodes.Unaligned => OpCodes.Unaligned, - InternalOpCodes.Unbox => OpCodes.Unbox, - InternalOpCodes.UnboxAny => OpCodes.Unbox_Any, - InternalOpCodes.Volatile => OpCodes.Volatile, - InternalOpCodes.Xor => OpCodes.Xor, - _ => throw new NotImplementedException(), - }; - } - private Identifier PeekIdentifier() - { - var position = reader.BaseStream.Position; - var identifier = ReadIdentifier(); - reader.BaseStream.Position = position; - return identifier; - } - private void ReadFunction() - { - var functionTypeName = ReadString(); - var functionName = ReadString(); - Console.WriteLine($"Linking function {functionName}"); - var functionParameterCount = reader.ReadUInt64(); - for (ulong i = 0; i < functionParameterCount; i++) - { - ReadString(); - } - - var method = new MethodDefinition(functionName, MethodAttributes.Public | MethodAttributes.Static, assembly.MainModule.TypeSystem.Void); - programType.Methods.Add(method); - var processor = method.Body.GetILProcessor(); - - try - { - while (true) - { - var identifier = ReadIdentifier(); - if (identifier != Identifier.Instruction) - { - break; - } - - var opCode = ReadOpCode(); - if (opCode == OpCodes.Call) - { - ReadIdentifier(); - EmitCall(processor, ReadString()); - continue; - } - switch (PeekIdentifier()) - { - case Identifier.String: - ReadIdentifier(); - var stringValue = ReadString(); - processor.Emit(opCode, stringValue); - break; - default: - break; - } - } - } - catch (EndOfStreamException) { } - processor.Emit(OpCodes.Ret); - - if (functionName == "main") - { - assembly.EntryPoint = method; - } - } - - private void EmitCall(ILProcessor processor, string methodName) - { - // Built-in functions - if (methodName == "println") - { - processor.Emit(OpCodes.Call, printlnMethod); - } - } - - private string ReadString() - { - var stringLength = reader.ReadUInt64(); - var bytes = reader.ReadBytes((int)stringLength); - var value = Encoding.UTF8.GetString(bytes); - return value; - } - - public void Export() - { - assembly.Write(ModuleName); - } -} diff --git a/src/.NET Linker/Program.cs b/src/.NET Linker/Program.cs deleted file mode 100644 index 1715c13..0000000 --- a/src/.NET Linker/Program.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Diagnostics; -using Jvav.Linker; - -namespace Jvav; - -internal class Program -{ - public static void Main(string[] args) - { - foreach (var arg in args) - { - Console.WriteLine($"linking {Path.GetFileName(arg)}"); - Linking(arg); - } - - if (Debugger.IsAttached) - { - while (true) - { - var input = Console.ReadLine(); - if (string.IsNullOrWhiteSpace(input)) - { - return; - } - - Linking(input); - } - } - } - - private static void Linking(string inputFile) - { - try - { - using var inputStream = File.OpenRead(inputFile); - var linker = new LinkingReader(inputStream); - - var linkerVersion = linker.ReadLinkerVersion(); - switch (linkerVersion) - { - case 1: - LinkingV1(linker); - break; - default: - Console.WriteLine($"error: unsupported linker version {linkerVersion}"); - break; - } - } - catch (Exception exception) - { - try - { - Console.WriteLine($"error: failed to open file '{Path.GetFileName(inputFile)}', error:\n - {exception.Message}"); - } - catch (Exception innerException) - { - Console.WriteLine($"error: failed to open file '{inputFile}', errors:\n - {exception.Message}\n - {innerException.Message}"); - } - } - } - - private static void LinkingV1(LinkingReader reader) - { - try - { - var linker = reader.LinkV1(); - Console.WriteLine($"linking {linker.ModuleName} with linker version 1"); - - linker.Export(); - } - catch (Exception exception) - { - Console.WriteLine($"error: failed to read linking data, error:\n - {exception}"); - } - } -} \ No newline at end of file diff --git a/src/.NET Linker/mscorlib.dll b/src/.NET Linker/mscorlib.dll deleted file mode 100755 index bde164e..0000000 Binary files a/src/.NET Linker/mscorlib.dll and /dev/null differ diff --git a/src/Mamba/Code Analysis/Binding/Binder.cpp b/src/Mamba/Code Analysis/Binding/Binder.cpp index df44f72..bf08fec 100644 --- a/src/Mamba/Code Analysis/Binding/Binder.cpp +++ b/src/Mamba/Code Analysis/Binding/Binder.cpp @@ -1,148 +1,99 @@ #include "Binder.h" - -#include -#include - -#include - -#include "AssignmentExpressionSyntax.h" -#include "BinaryExpressionSyntax.h" -#include "BlockStatementSyntax.h" -#include "BoundAssignmentExpression.h" -#include "BoundBinaryExpression.h" -#include "BoundBinaryOperator.h" -#include "BoundBlockStatement.h" #include "BoundCallExpression.h" -#include "BoundCompilationUnit.h" #include "BoundCompoundAssignmentExpression.h" -#include "BoundConstant.h" -#include "BoundDoWhileStatement.h" -#include "BoundExpression.h" #include "BoundExpressionStatement.h" -#include "BoundForStatement.h" -#include "BoundFunctionDeclaration.h" -#include "BoundIfStatement.h" -#include "BoundLiteralExpression.h" -#include "BoundNodeKind.h" -#include "BoundReturnStatement.h" -#include "BoundScope.h" -#include "BoundStatement.h" -#include "BoundUnaryExpression.h" -#include "BoundUnaryOperator.h" -#include "BoundVariableDeclaration.h" -#include "BoundVariableExpression.h" -#include "BoundWhileStatement.h" -#include "BreakStatementSyntax.h" -#include "CallExpressionSyntax.h" -#include "CompilationUnitSyntax.h" -#include "ContinueStatementSyntax.h" -#include "DoWhileStatementSyntax.h" -#include "ElseClauseSyntax.h" -#include "ExpressionStatementSyntax.h" -#include "ExpressionSyntax.h" -#include "ForStatementSyntax.h" -#include "FunctionDeclarationSyntax.h" -#include "FunctionSymbol.h" -#include "IfStatementSyntax.h" -#include "LiteralExpressionSyntax.h" #include "MambaCore.h" -#include "NameExpressionSyntax.h" -#include "ParameterSymbol.h" -#include "ParameterSyntax.h" -#include "ParenthesizedExpressionSyntax.h" -#include "ReturnStatementSyntax.h" -#include "StatementSyntax.h" -#include "Symbol.h" #include "SyntaxFacts.h" -#include "SyntaxKind.h" -#include "SyntaxTree.h" -#include "TypeClauseSyntax.h" -#include "TypeSymbol.h" -#include "UnaryExpressionSyntax.h" -#include "VariableDeclarationSyntax.h" -#include "WhileStatementSyntax.h" +#include using namespace Mamba; -std::shared_ptr Binder::BindCompilationUnit() noexcept +BoundCompilationUnit* Binder::BindCompilationUnit() noexcept { - const auto Root = SyntaxTree->Root(); + auto Root = SyntaxTree->Root(); for (auto&& Member : Root->Members) { BindMember(Member); } - return std::make_shared(Root, Scope); + return new BoundCompilationUnit(Root, Scope); } -void Binder::BindMember(const std::shared_ptr Member) noexcept +void Binder::BindMember(const MemberSyntax* Member) noexcept { - if (const auto FunctionDeclaration = std::dynamic_pointer_cast(Member)) + if (auto FunctionDeclaration = dynamic_cast(Member)) { BindFunctionDeclaration(FunctionDeclaration); } } -void Binder::BindFunctionDeclaration(const std::shared_ptr FunctionDeclaration) noexcept +void Binder::BindFunctionDeclaration(const FunctionDeclarationSyntax* FunctionDeclaration) noexcept { auto FunctionScope = EnterScope(); - const auto Body = BindStatement(FunctionDeclaration->Body); - const auto BoundFunctionDeclaration = std::make_shared(FunctionDeclaration, Body, Scope); + auto Body = BindStatement(FunctionDeclaration->Body); + auto BoundFunctionDeclaration = new class BoundFunctionDeclaration(FunctionDeclaration, Body); FunctionScope.PreLeave(); + DeclareFunction(FunctionDeclaration, BoundFunctionDeclaration); } void Binder::DeclareFunction( - const std::shared_ptr FunctionDeclaration, - const std::shared_ptr BoundFunctionDeclaration + const FunctionDeclarationSyntax* FunctionDeclaration, + const BoundFunctionDeclaration* BoundFunctionDeclaration ) noexcept { - const auto Name = FunctionDeclaration->Identifier->Text; + auto Name = FunctionDeclaration->Identifier->Text(); auto Parameters = BindParameter(FunctionDeclaration); - const auto Type = BindTypeClause(FunctionDeclaration->Type); - const auto FunctionSymbol = std::make_shared( - Name, - std::move(Parameters), - Type ? Type : TypeSymbol::Void, - BoundFunctionDeclaration - ); + auto Type = BindTypeClause(FunctionDeclaration->Type); + auto FunctionSymbol = new class FunctionSymbol(Name, std::move(Parameters), Type ? Type : &TypeSymbol::Void, BoundFunctionDeclaration); Scope->Declare(FunctionSymbol); } -std::vector> Binder::BindParameter( - const std::shared_ptr FunctionDeclaration +std::vector Binder::BindParameter( + const FunctionDeclarationSyntax* FunctionDeclaration ) noexcept { - const auto Parameters = FunctionDeclaration->Parameters->Nodes(); - - auto ParameterSymbols = std::vector>(); + auto Parameters = FunctionDeclaration->Parameters.Nodes(); + auto ParameterSymbols = std::vector(); ParameterSymbols.reserve(Parameters.size()); +#if __cpp_lib_ranges_enumerate >= 202302L + for (auto [Index, Parameter] : + Parameters | + std::views::transform([](auto&& Node) { return dynamic_cast(Node); }) | std::views::enumerate) + { + const auto Name = Parameter->Identifier->Text(); + const auto Type = new TypeSymbol(Parameter->Type->Identifier->Text()); + const auto ParameterSymbol = new class ParameterSymbol(Name, Type, Index); + Scope->Declare(ParameterSymbol); + } +#else auto Index = 0; - for (auto&& Parameter : Parameters | std::views::transform([](auto&& Node) - { return std::dynamic_pointer_cast(Node); })) + for (auto&& Parameter : + Parameters | std::views::transform([](auto&& Node) { return dynamic_cast(Node); })) { ++Index; - const auto Name = Parameter->Identifier->Text; - const auto Type = std::make_shared(Parameter->Type->Identifier->Text); - const auto ParameterSymbol = std::make_shared(Name, Type, Index); + const auto Name = Parameter->Identifier->Text(); + const auto Type = new TypeSymbol(Parameter->Type->Identifier->Text()); + const auto ParameterSymbol = new class ParameterSymbol(Name, Type, Index); Scope->Declare(ParameterSymbol); } return ParameterSymbols; +#endif } -std::shared_ptr Binder::BindStatement(const std::shared_ptr Statement) noexcept +BoundStatement* Binder::BindStatement(const StatementSyntax* Statement) noexcept { - const auto BoundStatement = BindStatementInternal(Statement); - if (const auto BoundExpressionStatement = std::dynamic_pointer_cast(BoundStatement)) + auto BoundStatement = BindStatementInternal(Statement); + if (auto BoundExpressionStatement = dynamic_cast(BoundStatement)) { // The following expressions' values can be discarded by default. - const auto IsAllowedExpression = + auto IsAllowedExpression = BoundExpressionStatement->Expression->Kind() == BoundNodeKind::AssignmentExpression || BoundExpressionStatement->Expression->Kind() == BoundNodeKind::CallExpression || BoundExpressionStatement->Expression->Kind() == BoundNodeKind::CompoundAssignmentExpression; @@ -156,128 +107,133 @@ std::shared_ptr Binder::BindStatement(const std::shared_pt return BoundStatement; } -std::shared_ptr Binder::BindStatementInternal(const std::shared_ptr Statement) noexcept +BoundStatement* Binder::BindStatementInternal(const StatementSyntax* Statement) noexcept { switch (Statement->Kind()) { case SyntaxKind::BlockStatement: - return BindBlockStatement(std::dynamic_pointer_cast(Statement)); + return BindBlockStatement(static_cast(Statement)); case SyntaxKind::VariableDeclaration: - return BindVariableDeclaration(std::dynamic_pointer_cast(Statement)); + return BindVariableDeclaration(static_cast(Statement)); case SyntaxKind::IfStatement: - return BindIfStatement(std::dynamic_pointer_cast(Statement)); + return BindIfStatement(static_cast(Statement)); case SyntaxKind::WhileStatement: - return BindWhileStatement(std::dynamic_pointer_cast(Statement)); + return BindWhileStatement(static_cast(Statement)); case SyntaxKind::DoWhileStatement: - return BindDoWhileStatement(std::dynamic_pointer_cast(Statement)); + return BindDoWhileStatement(static_cast(Statement)); case SyntaxKind::ForStatement: - return BindForStatement(std::dynamic_pointer_cast(Statement)); + return BindForStatement(static_cast(Statement)); case SyntaxKind::BreakStatement: - return BindBreakStatement(std::dynamic_pointer_cast(Statement)); + return BindBreakStatement(static_cast(Statement)); case SyntaxKind::ContinueStatement: - return BindContinueStatement(std::dynamic_pointer_cast(Statement)); + return BindContinueStatement(static_cast(Statement)); case SyntaxKind::ReturnStatement: - return BindReturnStatement(std::dynamic_pointer_cast(Statement)); + return BindReturnStatement(static_cast(Statement)); case SyntaxKind::ExpressionStatement: - return BindExpressionStatement(std::dynamic_pointer_cast(Statement)); + return BindExpressionStatement(static_cast(Statement)); default: +#ifdef DEBUG fast_io::io::perrln("Unexpected syntax: {}", fast_io::mnp::code_cvt(SyntaxFacts::ToString(Statement->Kind()))); + fast_io::fast_terminate(); +#else std::unreachable(); +#endif } } -std::shared_ptr Binder::BindBlockStatement(const std::shared_ptr BlockStatement) noexcept +BoundBlockStatement* Binder::BindBlockStatement(const BlockStatementSyntax* BlockStatement) noexcept { - auto BoundStatements = std::vector>(); - BoundStatements.reserve(BlockStatement->Statements.size()); - - const auto BlockScope = EnterScope(); + auto BlockScope = EnterScope(); - for (auto&& Statement : BlockStatement->Statements) - { - BoundStatements.emplace_back(Hatcher([&] - { return BindStatement(Statement); })); - } + auto BoundStatements = BlockStatement->Statements | + std::views::transform([&](auto Statement) -> const BoundStatement* { return BindStatement(Statement); }) | + std::ranges::to(); - return std::make_shared(BlockStatement, BoundStatements); + return new BoundBlockStatement(BlockStatement, std::move(BoundStatements)); } -std::shared_ptr Binder::BindExpressionStatement(const std::shared_ptr ExpressionStatement) noexcept +BoundExpressionStatement* Binder::BindExpressionStatement(const ExpressionStatementSyntax* ExpressionStatement) noexcept { - const auto Expression = BindExpression(ExpressionStatement->Expression); - return std::make_shared(ExpressionStatement, Expression); + auto Expression = BindExpression(ExpressionStatement->Expression); + return new BoundExpressionStatement(ExpressionStatement, Expression); } -std::shared_ptr Binder::BindExpression(const std::shared_ptr Expression) noexcept +BoundExpression* Binder::BindExpression(const ExpressionSyntax* Expression) noexcept { switch (Expression->Kind()) { case SyntaxKind::ParenthesizedExpression: - return BindParenthesizedExpression(std::dynamic_pointer_cast(Expression)); + return BindParenthesizedExpression(static_cast(Expression)); case SyntaxKind::LiteralExpression: - return BindLiteralExpression(std::dynamic_pointer_cast(Expression)); + return BindLiteralExpression(static_cast(Expression)); case SyntaxKind::NameExpression: - return BindNameExpression(std::dynamic_pointer_cast(Expression)); + return BindNameExpression(static_cast(Expression)); case SyntaxKind::AssignmentExpression: - return BindAssignmentExpression(std::dynamic_pointer_cast(Expression)); + return BindAssignmentExpression(static_cast(Expression)); case SyntaxKind::UnaryExpression: - return BindUnaryExpression(std::dynamic_pointer_cast(Expression)); + return BindUnaryExpression(static_cast(Expression)); case SyntaxKind::BinaryExpression: - return BindBinaryExpression(std::dynamic_pointer_cast(Expression)); + return BindBinaryExpression(static_cast(Expression)); case SyntaxKind::CallExpression: - return BindCallExpression(std::dynamic_pointer_cast(Expression)); + return BindCallExpression(static_cast(Expression)); default: - fast_io::io::perrln("Unexpected {}", fast_io::mnp::code_cvt(SyntaxFacts::ToString(Expression->Kind())), ", expression expected."); +#ifdef DEBUG + InternalCompilerError( + std::source_location::current(), + "Unexpected {}", + fast_io::mnp::code_cvt(SyntaxFacts::ToString(Expression->Kind())), + ", expression expected." + ); +#else std::unreachable(); +#endif } } -std::shared_ptr Binder::BindVariableDeclaration(const std::shared_ptr VariableDeclaration) noexcept +BoundVariableDeclaration* Binder::BindVariableDeclaration(const VariableDeclarationSyntax* VariableDeclaration) noexcept { - const auto IsReadOnly = VariableDeclaration->Keyword->Kind() == SyntaxKind::LetKeyword; - const auto Type = BindTypeClause(VariableDeclaration->TypeClause); - const auto Initializer = BindExpression(VariableDeclaration->Initializer); - const auto VariableType = Type ? Type : Initializer->Type(); - const auto Variable = BindVariableDeclaration( + auto IsReadOnly = VariableDeclaration->Keyword->Kind() == SyntaxKind::LetKeyword; + auto Type = BindTypeClause(VariableDeclaration->TypeClause); + auto Initializer = BindExpression(VariableDeclaration->Initializer); + auto VariableType = Type ? Type : Initializer->Type(); + auto Variable = BindVariableDeclaration( VariableDeclaration->Identifier, IsReadOnly, VariableType, Initializer->ConstantValue() ); - return std::make_shared(VariableDeclaration, Variable, Initializer); + Scope->Declare(Variable); + return new BoundVariableDeclaration(VariableDeclaration, Variable, Initializer); } -std::shared_ptr Binder::BindVariableDeclaration( - const std::shared_ptr Identifier, - const bool IsReadOnly, - const std::shared_ptr Type, - const NullableSharedPtr Constant -) noexcept +VariableSymbol* Binder::BindVariableDeclaration(const SyntaxToken* Identifier, bool IsReadOnly, const TypeSymbol* Type, Constant Constant) noexcept { - const auto Name = Identifier->Text; - if (!Name) + auto Name = Identifier->Text(); + if (Name.empty()) { - return std::make_shared(std::make_shared(TEXT("?")), IsReadOnly, Type, Constant); +#ifdef DEBUG + fast_io::io::perrln("Failed to bind variable declaration: empty identifier."); + fast_io::fast_terminate(); +#else + std::unreachable(); +#endif } if (!Scope->LookupVariable(Name).empty()) { - Diagnostics.ReportVariableAlreadyDeclared(Identifier->Location(), *Name); + Diagnostics.ReportVariableAlreadyDeclared(Identifier->Location(), Name); } - const auto Variable = std::make_shared(Name, IsReadOnly, Type, Constant); - - return Variable; + return new VariableSymbol(Name, IsReadOnly, Type, Constant); } -std::shared_ptr Binder::BindIfStatement(const std::shared_ptr IfStatement) noexcept +BoundIfStatement* Binder::BindIfStatement(const IfStatementSyntax* IfStatement) noexcept { - const auto Condition = BindExpression(IfStatement->Condition); - - if (Condition->ConstantValue()) + auto Condition = BindExpression(IfStatement->Condition); + if (Condition->ConstantValue().IsValid()) { - if (!Condition->ConstantValue()->Value->Value.BooleanValue) + if (!Condition->ConstantValue().Get()) { Diagnostics.ReportUnreachableCode(IfStatement->ElseClause->ElseStatement); } @@ -288,99 +244,102 @@ std::shared_ptr Binder::BindIfStatement(const std::shared_ } } - const auto ThenStatement = BindStatement(IfStatement->ThenStatement); - const auto ElseStatement = IfStatement->ElseClause ? nullptr : BindStatement(IfStatement->ElseClause->ElseStatement); - return std::make_shared(IfStatement, Condition, ThenStatement, ElseStatement); + auto ThenStatement = BindStatement(IfStatement->ThenStatement); + auto ElseStatement = IfStatement->ElseClause ? nullptr : BindStatement(IfStatement->ElseClause->ElseStatement); + return new BoundIfStatement(IfStatement, Condition, ThenStatement, ElseStatement); } -std::shared_ptr Binder::BindWhileStatement(const std::shared_ptr WhileStatement) noexcept +BoundWhileStatement* Binder::BindWhileStatement(const WhileStatementSyntax* WhileStatement) noexcept { - const auto WhileScope = EnterScope(); + auto WhileScope = EnterScope(); - const auto Condition = BindExpression(WhileStatement->Condition); + auto Condition = BindExpression(WhileStatement->Condition); - if (Condition->ConstantValue() && !Condition->ConstantValue()->Value->Value.BooleanValue) + if (Condition->ConstantValue().IsValid() && !Condition->ConstantValue().Get()) { Diagnostics.ReportUnreachableCode(WhileStatement->Body); } - const auto Body = BindStatement(WhileStatement->Body); - return std::make_shared(WhileStatement, Condition, Body); + auto Body = BindStatement(WhileStatement->Body); + return new BoundWhileStatement(WhileStatement, Condition, Body); } -std::shared_ptr Binder::BindDoWhileStatement(const std::shared_ptr DoWhileStatement) noexcept +BoundDoWhileStatement* Binder::BindDoWhileStatement(const DoWhileStatementSyntax* DoWhileStatement) noexcept { - const auto Body = BindStatement(DoWhileStatement->Body); - const auto Condition = BindExpression(DoWhileStatement->Condition); - return std::make_shared(DoWhileStatement, Body, Condition); + auto Body = BindStatement(DoWhileStatement->Body); + auto Condition = BindExpression(DoWhileStatement->Condition); + return new BoundDoWhileStatement(DoWhileStatement, Body, Condition); } -std::shared_ptr Binder::BindForStatement(const std::shared_ptr ForStatement) noexcept +BoundForStatement* Binder::BindForStatement(const ForStatementSyntax* ForStatement) noexcept { - const auto ForScope = EnterScope(); + auto ForScope = EnterScope(); - const auto InitStatement = BindStatement(ForStatement->InitStatement); - const auto Condition = BindExpression(ForStatement->Condition); - const auto Expression = BindExpression(ForStatement->Expression); - const auto Body = BindStatement(ForStatement->Body); + auto InitStatement = BindStatement(ForStatement->InitStatement); + auto Condition = BindExpression(ForStatement->Condition); + auto Expression = BindExpression(ForStatement->Expression); + auto Body = BindStatement(ForStatement->Body); - return std::make_shared(ForStatement, InitStatement, Condition, Expression, Body); + return new BoundForStatement(ForStatement, InitStatement, Condition, Expression, Body); } -std::shared_ptr Binder::BindBreakStatement(const std::shared_ptr BreakStatement) noexcept +BoundStatement* Binder::BindBreakStatement(const BreakStatementSyntax* BreakStatement) noexcept { fast_io::io::perrln("Failed to bind break statement: not implemented yet."); return {}; } -std::shared_ptr Binder::BindContinueStatement(const std::shared_ptr ContinueStatement) noexcept +BoundStatement* Binder::BindContinueStatement(const ContinueStatementSyntax* ContinueStatement) noexcept { fast_io::io::perrln("Failed to bind continue statement: not implemented yet."); return {}; } -std::shared_ptr Binder::BindReturnStatement(const std::shared_ptr ReturnStatement) noexcept +BoundReturnStatement* Binder::BindReturnStatement(const ReturnStatementSyntax* ReturnStatement) noexcept { // TODO: Diagnostics const auto Expression = BindExpression(ReturnStatement->Expression); - return std::make_shared(ReturnStatement, Expression); + return new BoundReturnStatement(ReturnStatement, Expression); } -std::shared_ptr Binder::BindLiteralExpression(const std::shared_ptr LiteralExpression) noexcept +BoundLiteralExpression* Binder::BindLiteralExpression(const LiteralExpressionSyntax* LiteralExpression) noexcept { - return std::make_shared(LiteralExpression, LiteralExpression->Value); + return new BoundLiteralExpression(LiteralExpression, LiteralExpression->Value); } -std::shared_ptr Binder::BindNameExpression(const std::shared_ptr NameExpression) noexcept +BoundVariableExpression* Binder::BindNameExpression(const NameExpressionSyntax* NameExpression) noexcept { - const auto Name = NameExpression->IdentifierToken->Text; - const auto Variables = Scope->LookupVariable(Name); + auto Name = NameExpression->IdentifierToken->Text(); + auto Variables = Scope->LookupVariable(Name); if (Variables.empty()) { - // TODO: Diagnostics - undeclaraed identifier - return {}; + auto ErrorVariable = new VariableSymbol(TEXT(""), false, &TypeSymbol::Void, {}); + Scope->Declare(ErrorVariable); + + Diagnostics.ReportUndeclaredIdentifier(NameExpression->Location(), Name); + return new BoundVariableExpression(NameExpression, ErrorVariable); } else if (Variables.size() > 1) { - // TODO: Diagnostics - ambiguous identifier - return {}; + Diagnostics.ReportAmbiguousIdentifier(NameExpression->Location(), Name); + return new BoundVariableExpression(NameExpression, Variables.front()); } - return std::make_shared(NameExpression, Variables.front()); + return new BoundVariableExpression(NameExpression, Variables.front()); } -std::shared_ptr Binder::BindParenthesizedExpression(const std::shared_ptr ParenthesizedExpression) noexcept +BoundExpression* Binder::BindParenthesizedExpression(const ParenthesizedExpressionSyntax* ParenthesizedExpression) noexcept { return BindExpression(ParenthesizedExpression->Expression); } -std::shared_ptr Binder::BindUnaryExpression(const std::shared_ptr UnaryExpression) noexcept +BoundUnaryExpression* Binder::BindUnaryExpression(const UnaryExpressionSyntax* UnaryExpression) noexcept { - const auto BoundOperand = BindExpression(UnaryExpression->Operand); + auto BoundOperand = BindExpression(UnaryExpression->Operand); // TODO: Check operand type - const auto BoundOperator = BoundUnaryOperator::Bind( + auto BoundOperator = BoundUnaryOperator::Bind( UnaryExpression->OperatorToken->Kind(), BoundOperand->Type() ); @@ -390,10 +349,10 @@ std::shared_ptr Binder::BindUnaryExpression(const std::sh return {}; } - return std::make_shared(UnaryExpression, *BoundOperator, BoundOperand); + return new BoundUnaryExpression(UnaryExpression, *BoundOperator, BoundOperand); } -std::shared_ptr Binder::BindBinaryExpression(const std::shared_ptr BinaryExpression) noexcept +BoundBinaryExpression* Binder::BindBinaryExpression(const BinaryExpressionSyntax* BinaryExpression) noexcept { const auto BoundLeft = BindExpression(BinaryExpression->Left); const auto BoundRight = BindExpression(BinaryExpression->Right); @@ -411,15 +370,15 @@ std::shared_ptr Binder::BindBinaryExpression(const std::s return {}; } - return std::make_shared(BinaryExpression, BoundLeft, *BoundOperator, BoundRight); + return new BoundBinaryExpression(BinaryExpression, BoundLeft, *BoundOperator, BoundRight); } -std::shared_ptr Binder::BindAssignmentExpression(const std::shared_ptr AssignmentExpression) noexcept +BoundExpression* Binder::BindAssignmentExpression(const AssignmentExpressionSyntax* AssignmentExpression) noexcept { - const auto Name = AssignmentExpression->IdentifierToken->Text; - const auto BoundExpression = BindExpression(AssignmentExpression->Expression); + auto Name = AssignmentExpression->IdentifierToken->Text(); + auto BoundExpression = BindExpression(AssignmentExpression->Expression); - const auto Variables = Scope->LookupVariable(Name); + auto Variables = Scope->LookupVariable(Name); if (Variables.empty()) { // TODO: Diagnostics - undeclaraed identifier @@ -431,7 +390,7 @@ std::shared_ptr Binder::BindAssignmentExpression(const st return {}; } - const auto Variable = Variables.front(); + auto Variable = Variables.front(); if (Variable->IsConstant) { // TODO: Diagnostics - constant variable cannot be assigned @@ -439,12 +398,8 @@ std::shared_ptr Binder::BindAssignmentExpression(const st if (AssignmentExpression->AssignmentToken->Kind() != SyntaxKind::EqualsToken) { - const auto EquivalentOperatorTokenKind = SyntaxFacts::GetBinaryOperatorOfAssignmentOperator(AssignmentExpression->AssignmentToken->Kind()); - const auto BoundOperator = BoundBinaryOperator::Bind( - EquivalentOperatorTokenKind, - Variable->Type, - BoundExpression->Type() - ); + auto EquivalentOperatorTokenKind = SyntaxFacts::GetBinaryOperatorOfAssignmentOperator(AssignmentExpression->AssignmentToken->Kind()); + auto BoundOperator = BoundBinaryOperator::Bind(EquivalentOperatorTokenKind, Variable->Type, BoundExpression->Type()); if (!BoundOperator) { @@ -453,26 +408,21 @@ std::shared_ptr Binder::BindAssignmentExpression(const st } // TODO: implement conversion - return std::make_shared( - AssignmentExpression, - Variable, - *BoundOperator, - BoundExpression - ); + return new BoundCompoundAssignmentExpression(AssignmentExpression, Variable, *BoundOperator, BoundExpression); } - return std::make_shared(AssignmentExpression, Variable, BoundExpression); + return new BoundAssignmentExpression(AssignmentExpression, Variable, BoundExpression); } -std::shared_ptr Binder::BindCallExpression(const std::shared_ptr CallExpression) noexcept +BoundCallExpression* Binder::BindCallExpression(const CallExpressionSyntax* CallExpression) noexcept { - auto BoundArguments = std::vector>(); - BoundArguments.reserve(CallExpression->Arguments->Count()); + auto BoundArguments = std::vector(); + BoundArguments.reserve(CallExpression->Arguments.Count()); - for (auto&& Argument : CallExpression->Arguments->Nodes()) + for (auto&& Argument : CallExpression->Arguments.Nodes()) { // Argument is guaranteed to be a expression by the parser. - const auto BoundArgument = BindExpression(std::static_pointer_cast(Argument)); + const auto BoundArgument = BindExpression(static_cast(Argument)); // TODO: Use hatcher to avoid copy BoundArguments.emplace_back(BoundArgument); @@ -481,18 +431,18 @@ std::shared_ptr Binder::BindCallExpression(const std::sha // TODO: Refinement Jvav standard // [basic.lookup]/? : If the declarations found by name lookup all denote functions, // the declarations are said to form an overload set. - const auto FunctionSet = Scope->LookupFunction(CallExpression->Identifier->Text); + const auto FunctionSet = Scope->LookupFunction(CallExpression->Identifier->Text()); if (FunctionSet.empty()) { // TODO: Diagnostics - undeclaraed function - fast_io::io::perrln("Undeclaraed function '", fast_io::mnp::code_cvt(*CallExpression->Identifier->Text), "'"); + fast_io::io::perrln("Undeclaraed function '", fast_io::mnp::code_cvt(CallExpression->Identifier->Text()), "'"); return {}; } // TODO: Overload resolution. Before overload resolution is avaiable, function override is not permitted. const auto Function = FunctionSet.front(); - if (CallExpression->Arguments->Count() != Function->Parameters.size()) + if (CallExpression->Arguments.Count() != Function->Parameters.size()) { // TODO: Report argument count mismatch fast_io::io::perrln("Failed to bind call expression: argument count mismatch."); @@ -501,17 +451,17 @@ std::shared_ptr Binder::BindCallExpression(const std::sha // TODO: implement conversion - return std::make_shared(CallExpression, Function, std::move(BoundArguments)); + return new BoundCallExpression(CallExpression, Function, std::move(BoundArguments)); } -NullableSharedPtr Binder::BindTypeClause(const NullableSharedPtr TypeClause) noexcept +NullablePointer Binder::BindTypeClause(NullablePointer TypeClause) noexcept { if (!TypeClause) { return {}; } - const auto Types = Scope->LookupType(TypeClause->Identifier->Text); + const auto Types = Scope->LookupType(TypeClause->Identifier->Text()); if (Types.empty()) { // TODO: Diagnostics - undeclaraed type @@ -530,7 +480,7 @@ void Binder::DeclareBuiltinFunctions() noexcept { } -Binder::Binder(const std::shared_ptr SyntaxTree) noexcept : - Scope(std::make_shared(nullptr)), SyntaxTree(SyntaxTree) +Binder::Binder(const class SyntaxTree* SyntaxTree) noexcept : + Scope(new BoundScope(nullptr)), SyntaxTree(SyntaxTree) { } diff --git a/src/Mamba/Code Analysis/Binding/Binder.h b/src/Mamba/Code Analysis/Binding/Binder.h index 92af963..19a808b 100644 --- a/src/Mamba/Code Analysis/Binding/Binder.h +++ b/src/Mamba/Code Analysis/Binding/Binder.h @@ -1,58 +1,90 @@ #pragma once +#include "AssignmentExpressionSyntax.h" +#include "BinaryExpressionSyntax.h" +#include "BoundAssignmentExpression.h" +#include "BoundBinaryExpression.h" +#include "BoundBlockStatement.h" +#include "BoundCallExpression.h" +#include "BoundCompilationUnit.h" +#include "BoundDoWhileStatement.h" +#include "BoundExpression.h" +#include "BoundExpressionStatement.h" +#include "BoundForStatement.h" +#include "BoundFunctionDeclaration.h" +#include "BoundIfStatement.h" +#include "BoundLiteralExpression.h" +#include "BoundReturnStatement.h" +#include "BoundScope.h" +#include "BoundStatement.h" +#include "BoundUnaryExpression.h" +#include "BoundVariableDeclaration.h" +#include "BoundVariableExpression.h" +#include "BoundWhileStatement.h" +#include "BreakStatementSyntax.h" +#include "CallExpressionSyntax.h" +#include "CompilationUnitSyntax.h" +#include "Constant.h" +#include "ContinueStatementSyntax.h" #include "DiagnosticBag.h" +#include "DoWhileStatementSyntax.h" +#include "ExpressionStatementSyntax.h" +#include "ForStatementSyntax.h" +#include "FunctionDeclarationSyntax.h" +#include "IfStatementSyntax.h" +#include "LiteralExpressionSyntax.h" #include "MambaCore.h" +#include "NameExpressionSyntax.h" +#include "ParameterSymbol.h" +#include "ParenthesizedExpressionSyntax.h" +#include "ReturnStatementSyntax.h" #include "ScopeGuard.h" -#include +#include "SyntaxTree.h" +#include "UnaryExpressionSyntax.h" +#include "VariableDeclarationSyntax.h" +#include "WhileStatementSyntax.h" + #include namespace Mamba { class Binder { - std::shared_ptr Scope; - std::shared_ptr SyntaxTree; - DiagnosticBag Diagnostics; + BoundScope* Scope; + const class SyntaxTree* SyntaxTree; - void BindMember(const std::shared_ptr Member) noexcept; - void BindFunctionDeclaration(const std::shared_ptr FunctionDeclaration) noexcept; + void BindMember(const MemberSyntax* Member) noexcept; + void BindFunctionDeclaration(const FunctionDeclarationSyntax* FunctionDeclaration) noexcept; void DeclareFunction( - const std::shared_ptr FunctionDeclaration, - const std::shared_ptr BoundFunctionDeclaration + const FunctionDeclarationSyntax* FunctionDeclaration, + const BoundFunctionDeclaration* BoundFunctionDeclaration ) noexcept; - std::vector> BindParameter( - const std::shared_ptr FunctionDeclaration - ) noexcept; + VariableSymbol* BindVariableDeclaration(const SyntaxToken* Identifier, bool IsReadOnly, const TypeSymbol* Type, Constant Constant) noexcept; + std::vector BindParameter(const FunctionDeclarationSyntax* FunctionDeclaration) noexcept; - std::shared_ptr BindStatement(const std::shared_ptr Statement) noexcept; - std::shared_ptr BindStatementInternal(const std::shared_ptr Statement) noexcept; - std::shared_ptr BindBlockStatement(const std::shared_ptr BlockStatement) noexcept; - std::shared_ptr BindExpressionStatement(const std::shared_ptr ExpressionStatement) noexcept; - std::shared_ptr BindExpression(const std::shared_ptr Expression) noexcept; - std::shared_ptr BindVariableDeclaration(const std::shared_ptr VariableDeclaration) noexcept; - std::shared_ptr BindVariableDeclaration( - const std::shared_ptr Identifier, - const bool IsReadOnly, - const std::shared_ptr Type, - const NullableSharedPtr Constant - ) noexcept; - std::shared_ptr BindIfStatement(const std::shared_ptr IfStatement) noexcept; - std::shared_ptr BindWhileStatement(const std::shared_ptr WhileStatement) noexcept; - std::shared_ptr BindDoWhileStatement(const std::shared_ptr DoWhileStatement) noexcept; - std::shared_ptr BindForStatement(const std::shared_ptr ForStatement) noexcept; - std::shared_ptr BindBreakStatement(const std::shared_ptr BreakStatement) noexcept; - std::shared_ptr BindContinueStatement(const std::shared_ptr ContinueStatement) noexcept; - std::shared_ptr BindReturnStatement(const std::shared_ptr ReturnStatement) noexcept; - std::shared_ptr BindLiteralExpression(const std::shared_ptr LiteralExpression) noexcept; - std::shared_ptr BindNameExpression(const std::shared_ptr NameExpression) noexcept; - std::shared_ptr BindParenthesizedExpression(const std::shared_ptr ParenthesizedExpression) noexcept; - std::shared_ptr BindUnaryExpression(const std::shared_ptr UnaryExpression) noexcept; - std::shared_ptr BindBinaryExpression(const std::shared_ptr BinaryExpression) noexcept; - std::shared_ptr BindAssignmentExpression(const std::shared_ptr AssignmentExpression) noexcept; - std::shared_ptr BindCallExpression(const std::shared_ptr CallExpression) noexcept; - NullableSharedPtr BindTypeClause(const NullableSharedPtr TypeClause) noexcept; + BoundStatement* BindBreakStatement(const BreakStatementSyntax* BreakStatement) noexcept; + BoundExpression* BindParenthesizedExpression(const ParenthesizedExpressionSyntax* ParenthesizedExpression) noexcept; + BoundExpressionStatement* BindExpressionStatement(const ExpressionStatementSyntax* ExpressionStatement) noexcept; + BoundVariableDeclaration* BindVariableDeclaration(const VariableDeclarationSyntax* VariableDeclaration) noexcept; + BoundExpression* BindAssignmentExpression(const AssignmentExpressionSyntax* AssignmentExpression) noexcept; + NullablePointer BindTypeClause(NullablePointer TypeClause) noexcept; + BoundLiteralExpression* BindLiteralExpression(const LiteralExpressionSyntax* LiteralExpression) noexcept; + BoundDoWhileStatement* BindDoWhileStatement(const DoWhileStatementSyntax* DoWhileStatement) noexcept; + BoundBinaryExpression* BindBinaryExpression(const BinaryExpressionSyntax* BinaryExpression) noexcept; + BoundUnaryExpression* BindUnaryExpression(const UnaryExpressionSyntax* UnaryExpression) noexcept; + BoundReturnStatement* BindReturnStatement(const ReturnStatementSyntax* ReturnStatement) noexcept; + BoundVariableExpression* BindNameExpression(const NameExpressionSyntax* NameExpression) noexcept; + BoundStatement* BindContinueStatement(const ContinueStatementSyntax* ContinueStatement) noexcept; + BoundBlockStatement* BindBlockStatement(const BlockStatementSyntax* BlockStatement) noexcept; + BoundWhileStatement* BindWhileStatement(const WhileStatementSyntax* WhileStatement) noexcept; + BoundCallExpression* BindCallExpression(const CallExpressionSyntax* CallExpression) noexcept; + BoundForStatement* BindForStatement(const ForStatementSyntax* ForStatement) noexcept; + BoundStatement* BindStatementInternal(const StatementSyntax* Statement) noexcept; + BoundIfStatement* BindIfStatement(const IfStatementSyntax* IfStatement) noexcept; + BoundExpression* BindExpression(const ExpressionSyntax* Expression) noexcept; + BoundStatement* BindStatement(const StatementSyntax* Statement) noexcept; ScopeGuard EnterScope() noexcept; @@ -60,8 +92,10 @@ namespace Mamba void DeclareBuiltinFunction(); public: - [[nodiscard]] Binder(const std::shared_ptr SyntaxTree) noexcept; + DiagnosticBag Diagnostics; + + [[nodiscard]] Binder(const class SyntaxTree* SyntaxTree) noexcept; - std::shared_ptr BindCompilationUnit() noexcept; + BoundCompilationUnit* BindCompilationUnit() noexcept; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundAssignmentExpression.cpp b/src/Mamba/Code Analysis/Binding/BoundAssignmentExpression.cpp index f701bbe..38d1bb9 100644 --- a/src/Mamba/Code Analysis/Binding/BoundAssignmentExpression.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundAssignmentExpression.cpp @@ -3,20 +3,25 @@ using namespace Mamba; BoundAssignmentExpression::BoundAssignmentExpression( - const std::shared_ptr Syntax, - const std::shared_ptr Variable, - const std::shared_ptr Expression + const SyntaxNode* Syntax, + const VariableSymbol* Variable, + const BoundExpression* Expression ) noexcept : Super(Syntax), Variable(Variable), Expression(Expression) { } +BoundAssignmentExpression::~BoundAssignmentExpression() noexcept +{ + delete Expression; +} + BoundNodeKind BoundAssignmentExpression::Kind() const noexcept { return BoundNodeKind::AssignmentExpression; } -std::shared_ptr BoundAssignmentExpression::Type() const noexcept +const TypeSymbol* BoundAssignmentExpression::Type() const noexcept { return Expression->Type(); } \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundAssignmentExpression.h b/src/Mamba/Code Analysis/Binding/BoundAssignmentExpression.h index eb3fc6e..c6a5e1e 100644 --- a/src/Mamba/Code Analysis/Binding/BoundAssignmentExpression.h +++ b/src/Mamba/Code Analysis/Binding/BoundAssignmentExpression.h @@ -1,9 +1,8 @@ #pragma once -#include - #include "BoundExpression.h" #include "BoundNodeKind.h" +#include "VariableSymbol.h" namespace Mamba { @@ -13,15 +12,17 @@ namespace Mamba using Super = BoundExpression; [[nodiscard]] BoundAssignmentExpression( - const std::shared_ptr Syntax, - const std::shared_ptr Variable, - const std::shared_ptr Expression + const SyntaxNode* Syntax, + const VariableSymbol* Variable, + const BoundExpression* Expression ) noexcept; + ~BoundAssignmentExpression() noexcept override; + BoundNodeKind Kind() const noexcept override; - std::shared_ptr Type() const noexcept override; + const TypeSymbol* Type() const noexcept override; - const std::shared_ptr Variable; - const std::shared_ptr Expression; + const VariableSymbol* Variable; + const BoundExpression* Expression; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundBinaryExpression.cpp b/src/Mamba/Code Analysis/Binding/BoundBinaryExpression.cpp index 81d3a96..b23c259 100644 --- a/src/Mamba/Code Analysis/Binding/BoundBinaryExpression.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundBinaryExpression.cpp @@ -1,31 +1,36 @@ #include "BoundBinaryExpression.h" -#include "BoundConstant.h" #include "ConstantFolding.h" using namespace Mamba; BoundBinaryExpression::BoundBinaryExpression( - const std::shared_ptr Syntax, - const std::shared_ptr Left, + const SyntaxNode* Syntax, + const BoundExpression* Left, const BoundBinaryOperator& Operator, - const std::shared_ptr Right + const BoundExpression* Right ) noexcept : Super(Syntax), Left(Left), Operator(Operator), Right(Right) { } +BoundBinaryExpression::~BoundBinaryExpression() noexcept +{ + delete Left; + delete Right; +} + BoundNodeKind BoundBinaryExpression::Kind() const noexcept { return BoundNodeKind::BinaryExpression; } -std::shared_ptr BoundBinaryExpression::Type() const noexcept +const TypeSymbol* BoundBinaryExpression::Type() const noexcept { return Operator.Type; } -NullableSharedPtr BoundBinaryExpression::ConstantValue() const noexcept +Constant BoundBinaryExpression::ConstantValue() const noexcept { return ConstantFolding::Fold(Left, Operator, Right); } \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundBinaryExpression.h b/src/Mamba/Code Analysis/Binding/BoundBinaryExpression.h index d89c3ea..c33cee4 100644 --- a/src/Mamba/Code Analysis/Binding/BoundBinaryExpression.h +++ b/src/Mamba/Code Analysis/Binding/BoundBinaryExpression.h @@ -1,10 +1,8 @@ #pragma once -#include - +#include "BoundBinaryOperator.h" #include "BoundExpression.h" #include "BoundNodeKind.h" -#include "MambaCore.h" namespace Mamba { @@ -13,19 +11,15 @@ namespace Mamba public: using Super = BoundExpression; - [[nodiscard]] BoundBinaryExpression( - const std::shared_ptr Syntax, - const std::shared_ptr Left, - const class BoundBinaryOperator& Operator, - const std::shared_ptr Right - ) noexcept; + [[nodiscard]] BoundBinaryExpression(const SyntaxNode* Syntax, const BoundExpression* Left, const BoundBinaryOperator& Operator, const BoundExpression* Right) noexcept; + ~BoundBinaryExpression() noexcept override; BoundNodeKind Kind() const noexcept override; - std::shared_ptr Type() const noexcept override; - NullableSharedPtr ConstantValue() const noexcept override; + const TypeSymbol* Type() const noexcept override; + Constant ConstantValue() const noexcept override; - std::shared_ptr Left; - const class BoundBinaryOperator& Operator; - const std::shared_ptr Right; + const BoundExpression* Left; + const BoundBinaryOperator& Operator; + const BoundExpression* Right; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundBinaryOperator.cpp b/src/Mamba/Code Analysis/Binding/BoundBinaryOperator.cpp index be19896..69ca817 100644 --- a/src/Mamba/Code Analysis/Binding/BoundBinaryOperator.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundBinaryOperator.cpp @@ -2,112 +2,57 @@ #include -#include "SyntaxKind.h" -#include "TypeSymbol.h" - using namespace Mamba; -BoundBinaryOperator::BoundBinaryOperator( - const enum SyntaxKind SyntaxKind, - const BoundBinaryOperatorKind Kind, - const std::shared_ptr Type -) noexcept : - BoundBinaryOperator(SyntaxKind, Kind, Type, Type, Type) +BoundBinaryOperator::BoundBinaryOperator(SyntaxKind Kind, BoundBinaryOperatorKind BoundKind, const TypeSymbol* Type) noexcept : + BoundBinaryOperator(Kind, BoundKind, Type, Type, Type) { } -BoundBinaryOperator::BoundBinaryOperator( - const enum SyntaxKind SyntaxKind, - const BoundBinaryOperatorKind Kind, - const std::shared_ptr OperandType, - const std::shared_ptr ResultType -) noexcept : - BoundBinaryOperator(SyntaxKind, Kind, OperandType, OperandType, ResultType) +BoundBinaryOperator::BoundBinaryOperator(SyntaxKind Kind, BoundBinaryOperatorKind BoundKind, const TypeSymbol* OperandType, const TypeSymbol* ResultType) noexcept : + BoundBinaryOperator(Kind, BoundKind, OperandType, OperandType, ResultType) { } -BoundBinaryOperator::BoundBinaryOperator( - const enum SyntaxKind SyntaxKind, - const BoundBinaryOperatorKind Kind, - const std::shared_ptr LeftType, - const std::shared_ptr RightType, - const std::shared_ptr ResultType -) noexcept : - SyntaxKind(SyntaxKind), Kind(Kind), LeftType(LeftType), RightType(RightType), Type(ResultType) +BoundBinaryOperator::BoundBinaryOperator(SyntaxKind Kind, BoundBinaryOperatorKind BoundKind, const TypeSymbol* LeftType, const TypeSymbol* RightType, const TypeSymbol* ResultType) noexcept : + Kind(Kind), BoundKind(BoundKind), LeftType(LeftType), RightType(RightType), Type(ResultType) { } BoundBinaryOperator BoundBinaryOperator::Operators[]{ - BoundBinaryOperator(SyntaxKind::PlusToken, BoundBinaryOperatorKind::Addition, TypeSymbol::Int), - BoundBinaryOperator(SyntaxKind::MinusToken, BoundBinaryOperatorKind::Subtraction, TypeSymbol::Int), - BoundBinaryOperator(SyntaxKind::StarToken, BoundBinaryOperatorKind::Multiplication, TypeSymbol::Int), - BoundBinaryOperator(SyntaxKind::SlashToken, BoundBinaryOperatorKind::Division, TypeSymbol::Int), - BoundBinaryOperator(SyntaxKind::AmpersandToken, BoundBinaryOperatorKind::BitwiseAnd, TypeSymbol::Int), - BoundBinaryOperator(SyntaxKind::PipeToken, BoundBinaryOperatorKind::BitwiseOr, TypeSymbol::Int), - BoundBinaryOperator(SyntaxKind::HatToken, BoundBinaryOperatorKind::BitwiseXor, TypeSymbol::Int), - BoundBinaryOperator( - SyntaxKind::EqualsEqualsToken, - BoundBinaryOperatorKind::Equals, - TypeSymbol::Int, - TypeSymbol::Bool - ), - BoundBinaryOperator( - SyntaxKind::BangEqualsToken, - BoundBinaryOperatorKind::NotEquals, - TypeSymbol::Int, - TypeSymbol::Bool - ), - BoundBinaryOperator(SyntaxKind::LessToken, BoundBinaryOperatorKind::Less, TypeSymbol::Int, TypeSymbol::Bool), - BoundBinaryOperator( - SyntaxKind::LessOrEqualsToken, - BoundBinaryOperatorKind::LessOrEquals, - TypeSymbol::Int, - TypeSymbol::Bool - ), - BoundBinaryOperator(SyntaxKind::GreaterToken, BoundBinaryOperatorKind::Greater, TypeSymbol::Int, TypeSymbol::Bool), - BoundBinaryOperator( - SyntaxKind::GreaterOrEqualsToken, - BoundBinaryOperatorKind::GreaterOrEquals, - TypeSymbol::Int, - TypeSymbol::Bool - ), - - BoundBinaryOperator(SyntaxKind::AmpersandToken, BoundBinaryOperatorKind::BitwiseAnd, TypeSymbol::Bool), - BoundBinaryOperator(SyntaxKind::AmpersandAmpersandToken, BoundBinaryOperatorKind::LogicalAnd, TypeSymbol::Bool), - BoundBinaryOperator(SyntaxKind::PipeToken, BoundBinaryOperatorKind::BitwiseOr, TypeSymbol::Bool), - BoundBinaryOperator(SyntaxKind::PipePipeToken, BoundBinaryOperatorKind::LogicalOr, TypeSymbol::Bool), - BoundBinaryOperator(SyntaxKind::HatToken, BoundBinaryOperatorKind::BitwiseXor, TypeSymbol::Bool), - BoundBinaryOperator(SyntaxKind::EqualsEqualsToken, BoundBinaryOperatorKind::Equals, TypeSymbol::Bool), - BoundBinaryOperator(SyntaxKind::BangEqualsToken, BoundBinaryOperatorKind::NotEquals, TypeSymbol::Bool), - - BoundBinaryOperator(SyntaxKind::PlusToken, BoundBinaryOperatorKind::Addition, TypeSymbol::String), - BoundBinaryOperator( - SyntaxKind::EqualsEqualsToken, - BoundBinaryOperatorKind::Equals, - TypeSymbol::String, - TypeSymbol::Bool - ), - BoundBinaryOperator( - SyntaxKind::BangEqualsToken, - BoundBinaryOperatorKind::NotEquals, - TypeSymbol::String, - TypeSymbol::Bool - ), + BoundBinaryOperator(SyntaxKind::PlusToken, BoundBinaryOperatorKind::Addition, &TypeSymbol::Int), + BoundBinaryOperator(SyntaxKind::MinusToken, BoundBinaryOperatorKind::Subtraction, &TypeSymbol::Int), + BoundBinaryOperator(SyntaxKind::StarToken, BoundBinaryOperatorKind::Multiplication, &TypeSymbol::Int), + BoundBinaryOperator(SyntaxKind::SlashToken, BoundBinaryOperatorKind::Division, &TypeSymbol::Int), + BoundBinaryOperator(SyntaxKind::AmpersandToken, BoundBinaryOperatorKind::BitwiseAnd, &TypeSymbol::Int), + BoundBinaryOperator(SyntaxKind::PipeToken, BoundBinaryOperatorKind::BitwiseOr, &TypeSymbol::Int), + BoundBinaryOperator(SyntaxKind::HatToken, BoundBinaryOperatorKind::BitwiseXor, &TypeSymbol::Int), + BoundBinaryOperator(SyntaxKind::EqualsEqualsToken, BoundBinaryOperatorKind::Equals, &TypeSymbol::Int, &TypeSymbol::Bool), + BoundBinaryOperator(SyntaxKind::BangEqualsToken, BoundBinaryOperatorKind::NotEquals, &TypeSymbol::Int, &TypeSymbol::Bool), + BoundBinaryOperator(SyntaxKind::LessToken, BoundBinaryOperatorKind::Less, &TypeSymbol::Int, &TypeSymbol::Bool), + BoundBinaryOperator(SyntaxKind::LessOrEqualsToken, BoundBinaryOperatorKind::LessOrEquals, &TypeSymbol::Int, &TypeSymbol::Bool), + BoundBinaryOperator(SyntaxKind::GreaterToken, BoundBinaryOperatorKind::Greater, &TypeSymbol::Int, &TypeSymbol::Bool), + BoundBinaryOperator(SyntaxKind::GreaterOrEqualsToken, BoundBinaryOperatorKind::GreaterOrEquals, &TypeSymbol::Int, &TypeSymbol::Bool), + + BoundBinaryOperator(SyntaxKind::AmpersandToken, BoundBinaryOperatorKind::BitwiseAnd, &TypeSymbol::Bool), + BoundBinaryOperator(SyntaxKind::AmpersandAmpersandToken, BoundBinaryOperatorKind::LogicalAnd, &TypeSymbol::Bool), + BoundBinaryOperator(SyntaxKind::PipeToken, BoundBinaryOperatorKind::BitwiseOr, &TypeSymbol::Bool), + BoundBinaryOperator(SyntaxKind::PipePipeToken, BoundBinaryOperatorKind::LogicalOr, &TypeSymbol::Bool), + BoundBinaryOperator(SyntaxKind::HatToken, BoundBinaryOperatorKind::BitwiseXor, &TypeSymbol::Bool), + BoundBinaryOperator(SyntaxKind::EqualsEqualsToken, BoundBinaryOperatorKind::Equals, &TypeSymbol::Bool), + BoundBinaryOperator(SyntaxKind::BangEqualsToken, BoundBinaryOperatorKind::NotEquals, &TypeSymbol::Bool), + + BoundBinaryOperator(SyntaxKind::PlusToken, BoundBinaryOperatorKind::Addition, &TypeSymbol::String), + BoundBinaryOperator(SyntaxKind::EqualsEqualsToken, BoundBinaryOperatorKind::Equals, &TypeSymbol::String, &TypeSymbol::Bool), + BoundBinaryOperator(SyntaxKind::BangEqualsToken, BoundBinaryOperatorKind::NotEquals, &TypeSymbol::String, &TypeSymbol::Bool), }; -NullablePointer BoundBinaryOperator::Bind( - const enum SyntaxKind SyntaxKind, - const std::shared_ptr LeftType, - const std::shared_ptr RightType -) noexcept +NullablePointer BoundBinaryOperator::Bind(SyntaxKind Kind, const TypeSymbol* LeftType, const TypeSymbol* RightType) noexcept { - const auto Result = std::ranges::find_if( + auto Result = std::ranges::find_if( std::ranges::begin(Operators), std::ranges::end(Operators), - [=](const BoundBinaryOperator& Operator) { - return Operator.SyntaxKind == SyntaxKind && Operator.LeftType == LeftType - && Operator.RightType == RightType; - } + [=](const BoundBinaryOperator& Operator) { return Operator.Kind == Kind && Operator.LeftType == LeftType && Operator.RightType == RightType; } ); if (Result == std::ranges::end(Operators)) { diff --git a/src/Mamba/Code Analysis/Binding/BoundBinaryOperator.h b/src/Mamba/Code Analysis/Binding/BoundBinaryOperator.h index 483067f..673e51c 100644 --- a/src/Mamba/Code Analysis/Binding/BoundBinaryOperator.h +++ b/src/Mamba/Code Analysis/Binding/BoundBinaryOperator.h @@ -1,36 +1,18 @@ #pragma once -#include - #include "MambaCore.h" #include "BoundBinaryOperatorKind.h" #include "SyntaxKind.h" +#include "TypeSymbol.h" namespace Mamba { class BoundBinaryOperator { - [[nodiscard]] BoundBinaryOperator( - const SyntaxKind SyntaxKind, - const BoundBinaryOperatorKind Kind, - const std::shared_ptr Type - ) noexcept; - - [[nodiscard]] BoundBinaryOperator( - const SyntaxKind SyntaxKind, - const BoundBinaryOperatorKind Kind, - const std::shared_ptr OperandType, - const std::shared_ptr ResultType - ) noexcept; - - [[nodiscard]] BoundBinaryOperator( - const SyntaxKind SyntaxKind, - const BoundBinaryOperatorKind Kind, - const std::shared_ptr LeftType, - const std::shared_ptr RightType, - const std::shared_ptr ResultType - ) noexcept; + [[nodiscard]] BoundBinaryOperator(SyntaxKind SyntaxKind, BoundBinaryOperatorKind Kind, const TypeSymbol* Type) noexcept; + [[nodiscard]] BoundBinaryOperator(SyntaxKind SyntaxKind, BoundBinaryOperatorKind Kind, const TypeSymbol* OperandType, const TypeSymbol* ResultType) noexcept; + [[nodiscard]] BoundBinaryOperator(SyntaxKind SyntaxKind, BoundBinaryOperatorKind Kind, const TypeSymbol* LeftType, const TypeSymbol* RightType, const TypeSymbol* ResultType) noexcept; BoundBinaryOperator(const BoundBinaryOperator&) = delete; BoundBinaryOperator(BoundBinaryOperator&&) = delete; @@ -39,20 +21,20 @@ namespace Mamba BoundBinaryOperator& operator=(BoundBinaryOperator&&) = delete; public: - const enum SyntaxKind SyntaxKind; - const BoundBinaryOperatorKind Kind; - const std::shared_ptr LeftType; - const std::shared_ptr RightType; - const std::shared_ptr Type; + enum SyntaxKind Kind; + BoundBinaryOperatorKind BoundKind; + const TypeSymbol* LeftType; + const TypeSymbol* RightType; + const TypeSymbol* Type; private: static BoundBinaryOperator Operators[]; public: static NullablePointer Bind( - const enum SyntaxKind SyntaxKind, - const std::shared_ptr LeftType, - const std::shared_ptr RightType + SyntaxKind Kind, + const TypeSymbol* LeftType, + const TypeSymbol* RightType ) noexcept; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundBlockStatement.cpp b/src/Mamba/Code Analysis/Binding/BoundBlockStatement.cpp index d04815f..0579bbd 100644 --- a/src/Mamba/Code Analysis/Binding/BoundBlockStatement.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundBlockStatement.cpp @@ -3,27 +3,22 @@ using namespace Mamba; BoundBlockStatement::BoundBlockStatement( - const std::shared_ptr Syntax, - const std::span> Statements + const SyntaxNode* Syntax, + std::vector&& Statements ) noexcept : - Super(Syntax), -#if __cpp_lib_containers_ranges == 202202L - Statements(std::from_range, Statements) -#else - Statements(Statements.begin(), Statements.end()) -#endif + Super(Syntax), Statements(std::move(Statements)) { } -BoundBlockStatement::BoundBlockStatement( - const std::shared_ptr Syntax, - std::vector>&& Statements -) noexcept : - Super(Syntax), Statements(std::move(Statements)) +BoundBlockStatement::~BoundBlockStatement() noexcept { + for (auto&& Statement : Statements) + { + delete Statement; + } } -BoundNodeKind Mamba::BoundBlockStatement::Kind() const noexcept +BoundNodeKind BoundBlockStatement::Kind() const noexcept { return BoundNodeKind::BlockStatement; } diff --git a/src/Mamba/Code Analysis/Binding/BoundBlockStatement.h b/src/Mamba/Code Analysis/Binding/BoundBlockStatement.h index 94c8054..a876dde 100644 --- a/src/Mamba/Code Analysis/Binding/BoundBlockStatement.h +++ b/src/Mamba/Code Analysis/Binding/BoundBlockStatement.h @@ -2,7 +2,6 @@ #include "BoundNodeKind.h" #include "BoundStatement.h" -#include namespace Mamba { @@ -11,18 +10,11 @@ namespace Mamba public: using Super = BoundStatement; - [[nodiscard]] BoundBlockStatement( - const std::shared_ptr Syntax, - const std::span> Statements - ) noexcept; - - [[nodiscard]] BoundBlockStatement( - const std::shared_ptr Syntax, - std::vector>&& Statements - ) noexcept; + [[nodiscard]] BoundBlockStatement(const SyntaxNode* Syntax, std::vector&& Statements) noexcept; + ~BoundBlockStatement() noexcept override; BoundNodeKind Kind() const noexcept override; - const std::vector> Statements; + std::vector Statements; }; }; // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundCallExpression.cpp b/src/Mamba/Code Analysis/Binding/BoundCallExpression.cpp index db609ce..984ecc2 100644 --- a/src/Mamba/Code Analysis/Binding/BoundCallExpression.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundCallExpression.cpp @@ -4,27 +4,20 @@ using namespace Mamba; BoundCallExpression::BoundCallExpression( - const std::shared_ptr Syntax, - const std::shared_ptr Function, - const std::span> Arguments + const SyntaxNode* Syntax, + const FunctionSymbol* Function, + std::vector&& Arguments ) noexcept : - Super(Syntax), - Function(Function), -#if __cpp_lib_containers_ranges == 202202L - Arguments(std::from_range, Arguments) -#else - Arguments(Arguments.begin(), Arguments.end()) -#endif + Super(Syntax), Function(Function), Arguments(std::move(Arguments)) { } -BoundCallExpression::BoundCallExpression( - const std::shared_ptr Syntax, - const std::shared_ptr Function, - std::vector>&& Arguments -) noexcept : - Super(Syntax), Function(Function), Arguments(std::move(Arguments)) +BoundCallExpression::~BoundCallExpression() noexcept { + for (auto Argument : Arguments) + { + delete Argument; + } } BoundNodeKind BoundCallExpression::Kind() const noexcept @@ -32,7 +25,7 @@ BoundNodeKind BoundCallExpression::Kind() const noexcept return BoundNodeKind::CallExpression; } -std::shared_ptr BoundCallExpression::Type() const noexcept +const TypeSymbol* BoundCallExpression::Type() const noexcept { return Function->Type; } diff --git a/src/Mamba/Code Analysis/Binding/BoundCallExpression.h b/src/Mamba/Code Analysis/Binding/BoundCallExpression.h index 9b2395c..fc3bca3 100644 --- a/src/Mamba/Code Analysis/Binding/BoundCallExpression.h +++ b/src/Mamba/Code Analysis/Binding/BoundCallExpression.h @@ -2,8 +2,8 @@ #include "BoundExpression.h" #include "BoundNodeKind.h" +#include "FunctionSymbol.h" -#include #include namespace Mamba @@ -14,21 +14,17 @@ namespace Mamba using Super = BoundExpression; [[nodiscard]] BoundCallExpression( - const std::shared_ptr Syntax, - const std::shared_ptr Function, - const std::span> Arguments + const SyntaxNode* Syntax, + const FunctionSymbol* Function, + std::vector&& Arguments ) noexcept; - [[nodiscard]] BoundCallExpression( - const std::shared_ptr Syntax, - const std::shared_ptr Function, - std::vector>&& Arguments - ) noexcept; + ~BoundCallExpression() noexcept override; BoundNodeKind Kind() const noexcept override; - std::shared_ptr Type() const noexcept override; + const TypeSymbol* Type() const noexcept override; - const std::shared_ptr Function; - const std::vector> Arguments; + const FunctionSymbol* Function; + const std::vector Arguments; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundCompilationUnit.cpp b/src/Mamba/Code Analysis/Binding/BoundCompilationUnit.cpp index e5a2367..de69e79 100644 --- a/src/Mamba/Code Analysis/Binding/BoundCompilationUnit.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundCompilationUnit.cpp @@ -1,11 +1,10 @@ #include "BoundCompilationUnit.h" -#include "BoundScope.h" using namespace Mamba; BoundCompilationUnit::BoundCompilationUnit( - const std::shared_ptr SyntaxNode, - const std::shared_ptr GlobalScope + const SyntaxNode* SyntaxNode, + const BoundScope* GlobalScope ) noexcept : Super(SyntaxNode), GlobalScope(GlobalScope) { diff --git a/src/Mamba/Code Analysis/Binding/BoundCompilationUnit.h b/src/Mamba/Code Analysis/Binding/BoundCompilationUnit.h index d53fee5..d302885 100644 --- a/src/Mamba/Code Analysis/Binding/BoundCompilationUnit.h +++ b/src/Mamba/Code Analysis/Binding/BoundCompilationUnit.h @@ -1,8 +1,8 @@ #pragma once -#include - #include "BoundNode.h" +#include "BoundScope.h" +#include "SyntaxNode.h" namespace Mamba { @@ -12,12 +12,12 @@ namespace Mamba using Super = BoundNode; [[nodiscard]] BoundCompilationUnit( - const std::shared_ptr SyntaxNode, - const std::shared_ptr GlobalScope + const SyntaxNode* SyntaxNode, + const BoundScope* GlobalScope ) noexcept; virtual BoundNodeKind Kind() const noexcept override; - const std::shared_ptr GlobalScope; + const BoundScope* GlobalScope; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundCompoundAssignmentExpression.cpp b/src/Mamba/Code Analysis/Binding/BoundCompoundAssignmentExpression.cpp index d709934..c219188 100644 --- a/src/Mamba/Code Analysis/Binding/BoundCompoundAssignmentExpression.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundCompoundAssignmentExpression.cpp @@ -3,21 +3,26 @@ using namespace Mamba; BoundCompoundAssignmentExpression::BoundCompoundAssignmentExpression( - const std::shared_ptr Syntax, - const std::shared_ptr Variable, + const SyntaxNode* Syntax, + const VariableSymbol* Variable, const BoundBinaryOperator& Operator, - const std::shared_ptr Expression + const BoundExpression* Expression ) noexcept : Super(Syntax), Variable(Variable), Operator(Operator), Expression(Expression) { } +BoundCompoundAssignmentExpression::~BoundCompoundAssignmentExpression() noexcept +{ + delete Expression; +} + BoundNodeKind BoundCompoundAssignmentExpression::Kind() const noexcept { return BoundNodeKind::CompoundAssignmentExpression; } -std::shared_ptr BoundCompoundAssignmentExpression::Type() const noexcept +const TypeSymbol* BoundCompoundAssignmentExpression::Type() const noexcept { return Expression->Type(); } diff --git a/src/Mamba/Code Analysis/Binding/BoundCompoundAssignmentExpression.h b/src/Mamba/Code Analysis/Binding/BoundCompoundAssignmentExpression.h index cc3cd24..7d15590 100644 --- a/src/Mamba/Code Analysis/Binding/BoundCompoundAssignmentExpression.h +++ b/src/Mamba/Code Analysis/Binding/BoundCompoundAssignmentExpression.h @@ -1,9 +1,9 @@ #pragma once -#include - +#include "BoundBinaryOperator.h" #include "BoundExpression.h" #include "BoundNodeKind.h" +#include "VariableSymbol.h" namespace Mamba { @@ -13,17 +13,19 @@ namespace Mamba using Super = BoundExpression; [[nodiscard]] BoundCompoundAssignmentExpression( - const std::shared_ptr Syntax, - const std::shared_ptr Variable, - const class BoundBinaryOperator& Operator, - const std::shared_ptr Expression + const SyntaxNode* Syntax, + const VariableSymbol* Variable, + const BoundBinaryOperator& Operator, + const BoundExpression* Expression ) noexcept; + ~BoundCompoundAssignmentExpression() noexcept override; + BoundNodeKind Kind() const noexcept override; - std::shared_ptr Type() const noexcept override; + const TypeSymbol* Type() const noexcept override; - const std::shared_ptr Variable; - const class BoundBinaryOperator& Operator; - const std::shared_ptr Expression; + const VariableSymbol* Variable; + const BoundBinaryOperator& Operator; + const BoundExpression* Expression; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundConstant.cpp b/src/Mamba/Code Analysis/Binding/BoundConstant.cpp deleted file mode 100644 index 42d9056..0000000 --- a/src/Mamba/Code Analysis/Binding/BoundConstant.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "BoundConstant.h" - -#include "Literal.h" - -using namespace Mamba; - -BoundConstant::BoundConstant(const std::shared_ptr Value) noexcept : Value(Value) {} - -const LiteralValue* BoundConstant::operator->() const noexcept -{ - return &Value->Value; -} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundConstant.h b/src/Mamba/Code Analysis/Binding/BoundConstant.h deleted file mode 100644 index 9f83012..0000000 --- a/src/Mamba/Code Analysis/Binding/BoundConstant.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "Literal.h" -#include - -namespace Mamba -{ - class BoundConstant - { - public: - [[nodiscard]] BoundConstant(const std::shared_ptr Value) noexcept; - - const std::shared_ptr Value; - - const LiteralValue* operator->() const noexcept; - }; -}; // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundDoWhileStatement.cpp b/src/Mamba/Code Analysis/Binding/BoundDoWhileStatement.cpp index 159373d..a268473 100644 --- a/src/Mamba/Code Analysis/Binding/BoundDoWhileStatement.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundDoWhileStatement.cpp @@ -5,15 +5,21 @@ using namespace Mamba; BoundDoWhileStatement::BoundDoWhileStatement( - const std::shared_ptr SyntaxNode, - const std::shared_ptr Body, - const std::shared_ptr Condition + const SyntaxNode* SyntaxNode, + const BoundStatement* Body, + const BoundExpression* Condition ) noexcept : Super(SyntaxNode), Body(Body), Condition(Condition) { } -BoundNodeKind Mamba::BoundDoWhileStatement::Kind() const noexcept +BoundDoWhileStatement::~BoundDoWhileStatement() noexcept +{ + delete Body; + delete Condition; +} + +BoundNodeKind BoundDoWhileStatement::Kind() const noexcept { return BoundNodeKind::DoWhileStatement; } diff --git a/src/Mamba/Code Analysis/Binding/BoundDoWhileStatement.h b/src/Mamba/Code Analysis/Binding/BoundDoWhileStatement.h index 9caad3d..bf40bff 100644 --- a/src/Mamba/Code Analysis/Binding/BoundDoWhileStatement.h +++ b/src/Mamba/Code Analysis/Binding/BoundDoWhileStatement.h @@ -1,7 +1,6 @@ #pragma once -#include - +#include "BoundExpression.h" #include "BoundNodeKind.h" #include "BoundStatement.h" @@ -13,14 +12,16 @@ namespace Mamba using Super = BoundStatement; [[nodiscard]] BoundDoWhileStatement( - const std::shared_ptr SyntaxNode, - const std::shared_ptr Body, - const std::shared_ptr Condition + const SyntaxNode* SyntaxNode, + const BoundStatement* Body, + const BoundExpression* Condition ) noexcept; + ~BoundDoWhileStatement() noexcept override; + BoundNodeKind Kind() const noexcept override; - const std::shared_ptr Body; - const std::shared_ptr Condition; + const BoundStatement* Body; + const BoundExpression* Condition; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundExpression.cpp b/src/Mamba/Code Analysis/Binding/BoundExpression.cpp index 854ee1f..2554456 100644 --- a/src/Mamba/Code Analysis/Binding/BoundExpression.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundExpression.cpp @@ -1,12 +1,11 @@ #include "BoundExpression.h" -#include "BoundConstant.h" - using namespace Mamba; -BoundExpression::BoundExpression(const std::shared_ptr Syntax) noexcept : Super(Syntax) {} +BoundExpression::BoundExpression(const SyntaxNode* Syntax) noexcept : + Super(Syntax) {} -NullableSharedPtr BoundExpression::ConstantValue() const noexcept +Constant BoundExpression::ConstantValue() const noexcept { - return nullptr; + return {}; } \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundExpression.h b/src/Mamba/Code Analysis/Binding/BoundExpression.h index d9d0969..cbb9a90 100644 --- a/src/Mamba/Code Analysis/Binding/BoundExpression.h +++ b/src/Mamba/Code Analysis/Binding/BoundExpression.h @@ -1,10 +1,8 @@ #pragma once -#include - -#include "MambaCore.h" - #include "BoundNode.h" +#include "Constant.h" +#include "TypeSymbol.h" namespace Mamba { @@ -13,9 +11,9 @@ namespace Mamba public: using Super = BoundNode; - [[nodiscard]] BoundExpression(const std::shared_ptr Syntax) noexcept; + [[nodiscard]] BoundExpression(const SyntaxNode* Syntax) noexcept; - virtual std::shared_ptr Type() const noexcept = 0; - virtual NullableSharedPtr ConstantValue() const noexcept; + virtual const TypeSymbol* Type() const noexcept = 0; + virtual Constant ConstantValue() const noexcept; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundExpressionStatement.cpp b/src/Mamba/Code Analysis/Binding/BoundExpressionStatement.cpp index e930a1a..fd64927 100644 --- a/src/Mamba/Code Analysis/Binding/BoundExpressionStatement.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundExpressionStatement.cpp @@ -3,13 +3,18 @@ using namespace Mamba; BoundExpressionStatement::BoundExpressionStatement( - const std::shared_ptr Syntax, - const std::shared_ptr Expression + const SyntaxNode* Syntax, + const BoundExpression* Expression ) noexcept : Super(Syntax), Expression(Expression) { } +BoundExpressionStatement::~BoundExpressionStatement() noexcept +{ + delete Expression; +} + BoundNodeKind BoundExpressionStatement::Kind() const noexcept { return BoundNodeKind::ExpressionStatement; diff --git a/src/Mamba/Code Analysis/Binding/BoundExpressionStatement.h b/src/Mamba/Code Analysis/Binding/BoundExpressionStatement.h index 7d24e1b..d415783 100644 --- a/src/Mamba/Code Analysis/Binding/BoundExpressionStatement.h +++ b/src/Mamba/Code Analysis/Binding/BoundExpressionStatement.h @@ -1,7 +1,6 @@ #pragma once -#include - +#include "BoundExpression.h" #include "BoundNodeKind.h" #include "BoundStatement.h" @@ -13,12 +12,13 @@ namespace Mamba using Super = BoundStatement; [[nodiscard]] BoundExpressionStatement( - const std::shared_ptr Syntax, - const std::shared_ptr Expression + const SyntaxNode* Syntax, + const BoundExpression* Expression ) noexcept; + ~BoundExpressionStatement() noexcept override; BoundNodeKind Kind() const noexcept override; - const std::shared_ptr Expression; + const BoundExpression* Expression; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundForStatement.cpp b/src/Mamba/Code Analysis/Binding/BoundForStatement.cpp index d5ca24d..7550385 100644 --- a/src/Mamba/Code Analysis/Binding/BoundForStatement.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundForStatement.cpp @@ -1,16 +1,15 @@ #include "BoundForStatement.h" #include "BoundExpression.h" -#include "BoundExpressionStatement.h" using namespace Mamba; BoundForStatement::BoundForStatement( - const std::shared_ptr Syntax, - const std::shared_ptr InitStatement, - const std::shared_ptr Condition, - const std::shared_ptr Expression, - const std::shared_ptr Body + const SyntaxNode* Syntax, + const BoundStatement* InitStatement, + const BoundExpression* Condition, + const BoundExpression* Expression, + const BoundStatement* Body ) noexcept : Super(Syntax), InitStatement(InitStatement), @@ -20,7 +19,15 @@ BoundForStatement::BoundForStatement( { } -BoundNodeKind Mamba::BoundForStatement::Kind() const noexcept +BoundForStatement::~BoundForStatement() noexcept +{ + delete InitStatement; + delete Condition; + delete Expression; + delete Body; +} + +BoundNodeKind BoundForStatement::Kind() const noexcept { return BoundNodeKind::ForStatement; } diff --git a/src/Mamba/Code Analysis/Binding/BoundForStatement.h b/src/Mamba/Code Analysis/Binding/BoundForStatement.h index cf1ca3f..990b543 100644 --- a/src/Mamba/Code Analysis/Binding/BoundForStatement.h +++ b/src/Mamba/Code Analysis/Binding/BoundForStatement.h @@ -1,7 +1,6 @@ #pragma once -#include - +#include "BoundExpression.h" #include "BoundNodeKind.h" #include "BoundStatement.h" @@ -13,18 +12,19 @@ namespace Mamba using Super = BoundStatement; [[nodiscard]] BoundForStatement( - const std::shared_ptr Syntax, - const std::shared_ptr InitStatement, - const std::shared_ptr Condition, - const std::shared_ptr Expression, - const std::shared_ptr Body + const SyntaxNode* Syntax, + const BoundStatement* InitStatement, + const BoundExpression* Condition, + const BoundExpression* Expression, + const BoundStatement* Body ) noexcept; + ~BoundForStatement() noexcept override; BoundNodeKind Kind() const noexcept override; - const std::shared_ptr InitStatement; - const std::shared_ptr Condition; - const std::shared_ptr Expression; - const std::shared_ptr Body; + const BoundStatement* InitStatement; + const BoundExpression* Condition; + const BoundExpression* Expression; + const BoundStatement* Body; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundFunctionDeclaration.cpp b/src/Mamba/Code Analysis/Binding/BoundFunctionDeclaration.cpp index eadca45..667d0d0 100644 --- a/src/Mamba/Code Analysis/Binding/BoundFunctionDeclaration.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundFunctionDeclaration.cpp @@ -2,15 +2,19 @@ using namespace Mamba; -Mamba::BoundFunctionDeclaration::BoundFunctionDeclaration( - const std::shared_ptr Syntax, - const std::shared_ptr Body, - const std::shared_ptr Scope +BoundFunctionDeclaration::BoundFunctionDeclaration( + const SyntaxNode* Syntax, + const BoundStatement* Body ) noexcept : - Super(Syntax), Body(Body), Scope(Scope) + Super(Syntax), Body(Body) { } +BoundFunctionDeclaration::~BoundFunctionDeclaration() noexcept +{ + delete Body; +} + BoundNodeKind BoundFunctionDeclaration::Kind() const noexcept { return BoundNodeKind::FunctionDeclaration; diff --git a/src/Mamba/Code Analysis/Binding/BoundFunctionDeclaration.h b/src/Mamba/Code Analysis/Binding/BoundFunctionDeclaration.h index 0adbd28..1c64b33 100644 --- a/src/Mamba/Code Analysis/Binding/BoundFunctionDeclaration.h +++ b/src/Mamba/Code Analysis/Binding/BoundFunctionDeclaration.h @@ -1,7 +1,5 @@ #pragma once -#include - #include "BoundStatement.h" namespace Mamba @@ -12,14 +10,14 @@ namespace Mamba using Super = BoundStatement; [[nodiscard]] BoundFunctionDeclaration( - const std::shared_ptr Syntax, - const std::shared_ptr Body, - const std::shared_ptr Scope + const SyntaxNode* Syntax, + const BoundStatement* Body ) noexcept; + ~BoundFunctionDeclaration() noexcept override; + virtual BoundNodeKind Kind() const noexcept override; - std::shared_ptr Body; - std::shared_ptr Scope; + const BoundStatement* Body; }; }; // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundIfStatement.cpp b/src/Mamba/Code Analysis/Binding/BoundIfStatement.cpp index 0f06039..939ef6f 100644 --- a/src/Mamba/Code Analysis/Binding/BoundIfStatement.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundIfStatement.cpp @@ -2,16 +2,18 @@ using namespace Mamba; -BoundIfStatement::BoundIfStatement( - const std::shared_ptr Syntax, - const std::shared_ptr Condition, - const std::shared_ptr ThenStatement, - const NullableSharedPtr ElseStatement -) noexcept : +BoundIfStatement::BoundIfStatement(const SyntaxNode* Syntax, const BoundExpression* Condition, const BoundStatement* ThenStatement, NullablePointer ElseStatement) noexcept : Super(Syntax), Condition(Condition), ThenStatement(ThenStatement), ElseStatement(ElseStatement) { } +BoundIfStatement::~BoundIfStatement() noexcept +{ + delete Condition; + delete ThenStatement; + delete ElseStatement; +} + BoundNodeKind BoundIfStatement::Kind() const noexcept { return BoundNodeKind::IfStatement; diff --git a/src/Mamba/Code Analysis/Binding/BoundIfStatement.h b/src/Mamba/Code Analysis/Binding/BoundIfStatement.h index 189ab5f..7a8e2ae 100644 --- a/src/Mamba/Code Analysis/Binding/BoundIfStatement.h +++ b/src/Mamba/Code Analysis/Binding/BoundIfStatement.h @@ -1,7 +1,6 @@ #pragma once -#include - +#include "BoundExpression.h" #include "BoundNodeKind.h" #include "BoundStatement.h" #include "MambaCore.h" @@ -13,17 +12,13 @@ namespace Mamba public: using Super = BoundStatement; - [[nodiscard]] BoundIfStatement( - const std::shared_ptr Syntax, - const std::shared_ptr Condition, - const std::shared_ptr ThenStatement, - const NullableSharedPtr ElseStatement - ) noexcept; + [[nodiscard]] BoundIfStatement(const SyntaxNode* Syntax, const BoundExpression* Condition, const BoundStatement* ThenStatement, NullablePointer ElseStatement) noexcept; + ~BoundIfStatement() noexcept override; BoundNodeKind Kind() const noexcept override; - const std::shared_ptr Condition; - const std::shared_ptr ThenStatement; - const NullableSharedPtr ElseStatement; + const BoundExpression* Condition; + const BoundStatement* ThenStatement; + NullablePointer ElseStatement; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundLiteralExpression.cpp b/src/Mamba/Code Analysis/Binding/BoundLiteralExpression.cpp index e0f3fa8..2429eba 100644 --- a/src/Mamba/Code Analysis/Binding/BoundLiteralExpression.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundLiteralExpression.cpp @@ -1,45 +1,18 @@ #include "BoundLiteralExpression.h" - -#include - -#include "BoundConstant.h" -#include "Literal.h" +#include "MambaCore.h" #include "TypeSymbol.h" -using namespace Mamba; +#include +#include +#include -std::shared_ptr GetType(const std::shared_ptr Value) noexcept -{ - switch (Value->Type) - { - case LiteralType::String: - return TypeSymbol::String; - case LiteralType::SignedInt: - return TypeSymbol::Int; - case LiteralType::Boolean: - return TypeSymbol::Bool; - - case LiteralType::Character: - case LiteralType::UnsignedByte: - case LiteralType::UnsignedShort: - case LiteralType::UnsignedInt: - case LiteralType::UnsignedLong: - case LiteralType::SignedByte: - case LiteralType::SignedShort: - case LiteralType::SignedLong: - case LiteralType::Double: - case LiteralType::Float: - case LiteralType::Empty: - default: - return TypeSymbol::Void; - } -} +using namespace Mamba; BoundLiteralExpression::BoundLiteralExpression( - const std::shared_ptr Syntax, - const std::shared_ptr Value + const SyntaxNode* Syntax, + Literal Value ) noexcept : - Super(Syntax), PrivateType(GetType(Value)), Value(Value) + Super(Syntax), Value(Value) { } @@ -48,12 +21,39 @@ BoundNodeKind BoundLiteralExpression::Kind() const noexcept return BoundNodeKind::LiteralExpression; } -std::shared_ptr BoundLiteralExpression::Type() const noexcept +const TypeSymbol* BoundLiteralExpression::Type() const noexcept { - return PrivateType; + return std::visit( + [](T) { + if constexpr (std::is_same_v) + { + return &TypeSymbol::String; + } + else if constexpr (std::is_same_v) + { + return &TypeSymbol::Int; + } + else if constexpr (std::is_same_v) + { + return &TypeSymbol::Bool; + } + else if constexpr (std::is_same_v) + { + return &TypeSymbol::Double; + } + else if constexpr (std::is_same_v) + { + InternalCompilerError(std::source_location::current(), "Literal expression with no empty type."); + return &TypeSymbol::Void; + } + + std::unreachable(); + }, + Value.Value + ); } -std::shared_ptr BoundLiteralExpression::ConstantValue() const noexcept +Constant BoundLiteralExpression::ConstantValue() const noexcept { - return std::make_shared(Value); + return std::visit([](auto Value) -> Constant { return Value; }, Value.Value); } diff --git a/src/Mamba/Code Analysis/Binding/BoundLiteralExpression.h b/src/Mamba/Code Analysis/Binding/BoundLiteralExpression.h index 37d537e..8415061 100644 --- a/src/Mamba/Code Analysis/Binding/BoundLiteralExpression.h +++ b/src/Mamba/Code Analysis/Binding/BoundLiteralExpression.h @@ -1,9 +1,8 @@ #pragma once -#include - #include "BoundExpression.h" #include "BoundNodeKind.h" +#include "Literal.h" namespace Mamba { @@ -13,16 +12,15 @@ namespace Mamba using Super = BoundExpression; [[nodiscard]] BoundLiteralExpression( - const std::shared_ptr Syntax, - const std::shared_ptr Value + const SyntaxNode* Syntax, + Literal Value ) noexcept; BoundNodeKind Kind() const noexcept override; - std::shared_ptr Type() const noexcept override; - std::shared_ptr ConstantValue() const noexcept override; + const TypeSymbol* Type() const noexcept override; + Constant ConstantValue() const noexcept override; private: - const std::shared_ptr PrivateType; - const std::shared_ptr Value; + Literal Value; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundNode.cpp b/src/Mamba/Code Analysis/Binding/BoundNode.cpp index 6caee37..07ed243 100644 --- a/src/Mamba/Code Analysis/Binding/BoundNode.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundNode.cpp @@ -2,4 +2,5 @@ using namespace Mamba; -BoundNode::BoundNode(const std::shared_ptr Syntax) noexcept : Syntax(Syntax) {} \ No newline at end of file +BoundNode::BoundNode(const SyntaxNode* Syntax) noexcept : + Syntax(Syntax) {} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundNode.h b/src/Mamba/Code Analysis/Binding/BoundNode.h index c80d234..9f1502d 100644 --- a/src/Mamba/Code Analysis/Binding/BoundNode.h +++ b/src/Mamba/Code Analysis/Binding/BoundNode.h @@ -1,20 +1,19 @@ #pragma once -#include - #include "BoundNodeKind.h" +#include "SyntaxNode.h" namespace Mamba { class BoundNode { protected: - [[nodiscard]] BoundNode(const std::shared_ptr Syntax) noexcept; + [[nodiscard]] BoundNode(const SyntaxNode* Syntax) noexcept; public: - virtual ~BoundNode() = default; + virtual ~BoundNode() noexcept = default; virtual BoundNodeKind Kind() const noexcept = 0; - const std::shared_ptr Syntax; + const SyntaxNode* Syntax; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundNopStatement.cpp b/src/Mamba/Code Analysis/Binding/BoundNopStatement.cpp index 5c5970d..62e9a17 100644 --- a/src/Mamba/Code Analysis/Binding/BoundNopStatement.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundNopStatement.cpp @@ -2,7 +2,8 @@ using namespace Mamba; -BoundNopStatement::BoundNopStatement(const std::shared_ptr Syntax) noexcept : Super(Syntax) {} +BoundNopStatement::BoundNopStatement(const SyntaxNode* Syntax) noexcept : + Super(Syntax) {} BoundNodeKind BoundNopStatement::Kind() const noexcept { diff --git a/src/Mamba/Code Analysis/Binding/BoundNopStatement.h b/src/Mamba/Code Analysis/Binding/BoundNopStatement.h index 9049927..3303101 100644 --- a/src/Mamba/Code Analysis/Binding/BoundNopStatement.h +++ b/src/Mamba/Code Analysis/Binding/BoundNopStatement.h @@ -12,7 +12,7 @@ namespace Mamba public: using Super = BoundStatement; - [[nodiscard]] BoundNopStatement(const std::shared_ptr Syntax) noexcept; + [[nodiscard]] BoundNopStatement(const SyntaxNode* Syntax) noexcept; BoundNodeKind Kind() const noexcept override; }; diff --git a/src/Mamba/Code Analysis/Binding/BoundReturnStatement.cpp b/src/Mamba/Code Analysis/Binding/BoundReturnStatement.cpp index 37479cf..13d68ad 100644 --- a/src/Mamba/Code Analysis/Binding/BoundReturnStatement.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundReturnStatement.cpp @@ -3,8 +3,8 @@ using namespace Mamba; BoundReturnStatement::BoundReturnStatement( - const std::shared_ptr Syntax, - const std::shared_ptr Expression + const SyntaxNode* Syntax, + const BoundExpression* Expression ) noexcept : Super(Syntax), Expression(Expression) { @@ -14,3 +14,8 @@ BoundNodeKind BoundReturnStatement::Kind() const noexcept { return BoundNodeKind::ReturnStatement; } + +BoundReturnStatement::~BoundReturnStatement() noexcept +{ + delete Expression; +} diff --git a/src/Mamba/Code Analysis/Binding/BoundReturnStatement.h b/src/Mamba/Code Analysis/Binding/BoundReturnStatement.h index aaacdba..01c3a06 100644 --- a/src/Mamba/Code Analysis/Binding/BoundReturnStatement.h +++ b/src/Mamba/Code Analysis/Binding/BoundReturnStatement.h @@ -1,7 +1,6 @@ #pragma once -#include - +#include "BoundExpression.h" #include "BoundStatement.h" namespace Mamba @@ -12,12 +11,13 @@ namespace Mamba using Super = BoundStatement; [[nodiscard]] BoundReturnStatement( - const std::shared_ptr Syntax, - const std::shared_ptr Expression + const SyntaxNode* Syntax, + const BoundExpression* Expression ) noexcept; + ~BoundReturnStatement() noexcept override; BoundNodeKind Kind() const noexcept override; - const std::shared_ptr Expression; + const BoundExpression* Expression; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundScope.cpp b/src/Mamba/Code Analysis/Binding/BoundScope.cpp index d42bf30..a494a07 100644 --- a/src/Mamba/Code Analysis/Binding/BoundScope.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundScope.cpp @@ -1,124 +1,117 @@ #include "BoundScope.h" -#include -#include - -#include "fast_io.h" -#include "fast_io_core_impl/codecvt/general.h" -#include "fast_io_core_impl/integers/impl.h" -#include "FunctionSymbol.h" -#include "ParameterSymbol.h" -#include "TypeSymbol.h" - using namespace Mamba; -BoundScope::BoundScope(const NullableSharedPtr Parent) noexcept : +BoundScope::BoundScope(NullablePointer Parent) noexcept : Parent(Parent) {} -void BoundScope::Declare(const std::shared_ptr Symbol) noexcept +BoundScope::~BoundScope() noexcept +{ + for (auto Child : Children) + { + delete Child; + } +} + +void BoundScope::Declare(const Symbol* Symbol) noexcept { - Symbols[*Symbol->Name].emplace_back(Symbol); + Symbols[Symbol->Name()].emplace_back(Symbol); } -std::shared_ptr BoundScope::DeclareScope() noexcept +BoundScope* BoundScope::DeclareScope() noexcept { - const auto ChildScope = std::make_shared(shared_from_this()); + const auto ChildScope = new BoundScope(this); Children.emplace_back(ChildScope); return ChildScope; } -std::vector> BoundScope::LookupVariable(const std::shared_ptr Name -) const noexcept +std::vector BoundScope::LookupVariable(StringView Name) const noexcept { - return Lookup(Name) | std::views::filter([](auto Symbol) - { return Symbol->IsVariable(); }) | - std::views::transform([](auto Symbol) - { return std::static_pointer_cast(Symbol); }) | + return Lookup(Name) | + std::views::filter([](auto Symbol) { return Symbol->IsVariable(); }) | + std::views::transform([](auto Symbol) { return static_cast(Symbol); }) | std::ranges::to(); } -std::vector> BoundScope::LookupFunction(const std::shared_ptr Name -) const noexcept +std::vector BoundScope::LookupFunction(StringView Name) const noexcept { - return Lookup(Name) | std::views::filter([&](auto Symbol) - { return Symbol->IsFunction(); }) | - std::views::transform([](auto Symbol) - { return std::static_pointer_cast(Symbol); }) | + return Lookup(Name) | + std::views::filter([&](auto Symbol) { return Symbol->IsFunction(); }) | + std::views::transform([](auto Symbol) { return static_cast(Symbol); }) | std::ranges::to(); } -std::vector> BoundScope::LookupType(const std::shared_ptr Name -) const noexcept +std::vector BoundScope::LookupType(StringView Name) const noexcept { - return Lookup(Name) | std::views::filter([](auto Symbol) - { return Symbol->IsType(); }) | - std::views::transform([](auto Symbol) - { return std::static_pointer_cast(Symbol); }) | + return Lookup(Name) | + std::views::filter([](auto Symbol) { return Symbol->IsType(); }) | + std::views::transform([](auto Symbol) { return static_cast(Symbol); }) | std::ranges::to(); } -std::vector> - BoundScope::LookupParameter(const std::shared_ptr Name) const noexcept +std::vector BoundScope::LookupParameter(StringView Name) const noexcept { - return Lookup(Name) | std::views::filter([](auto Symbol) - { return Symbol->IsParameter(); }) | - std::views::transform([](auto Symbol) - { return std::static_pointer_cast(Symbol); }) | + return Lookup(Name) | + std::views::filter([](auto Symbol) { return Symbol->IsParameter(); }) | + std::views::transform([](auto Symbol) { return static_cast(Symbol); }) | std::ranges::to(); } -std::vector> BoundScope::Lookup(const std::shared_ptr Name) const noexcept +std::vector BoundScope::Lookup(StringView Name) const noexcept { - const auto Result = Symbols.find(*Name); - if (Result != Symbols.end()) + const auto Result = Symbols.find(Name); + if (Result != Symbols.end()) [[unlikely]] { return Result->second; } - return Parent ? Parent->Lookup(Name) : std::vector>{}; + return Parent ? Parent->Lookup(Name) : std::vector{}; } -std::vector> BoundScope::DeclaredVariables() const noexcept +std::vector BoundScope::DeclaredVariables() const noexcept { - return Symbols | std::views::values | std::views::join | - std::views::filter([](auto Symbol) - { return Symbol->IsVariable(); }) | - std::views::transform([](auto Symbol) - { return std::static_pointer_cast(Symbol); }) | + return Symbols | + std::views::values | + std::views::join | + std::views::filter([](auto Symbol) { return Symbol->IsVariable(); }) | + std::views::transform([](auto Symbol) { return static_cast(Symbol); }) | std::ranges::to(); } -std::vector> BoundScope::DeclaredFunctions() const noexcept +std::vector BoundScope::DeclaredFunctions() const noexcept { - return Symbols | std::views::values | std::views::join | - std::views::filter([](auto Symbol) - { return Symbol->IsFunction(); }) | - std::views::transform([](auto Symbol) - { return std::static_pointer_cast(Symbol); }) | + return Symbols | + std::views::values | + std::views::join | + std::views::filter([](auto Symbol) { return Symbol->IsFunction(); }) | + std::views::transform([](auto Symbol) { return static_cast(Symbol); }) | std::ranges::to(); } -std::vector> BoundScope::DeclaredTypes() const noexcept +std::vector BoundScope::DeclaredTypes() const noexcept { - return Symbols | std::views::values | std::views::join | - std::views::filter([](auto Symbol) - { return Symbol->IsType(); }) | - std::views::transform([](auto Symbol) - { return std::static_pointer_cast(Symbol); }) | + return Symbols | + std::views::values | + std::views::join | + std::views::filter([](auto Symbol) { return Symbol->IsType(); }) | + std::views::transform([](auto Symbol) { return static_cast(Symbol); }) | std::ranges::to(); } -std::vector> BoundScope::DeclaredParameters() const noexcept +std::vector BoundScope::DeclaredParameters() const noexcept { - return Symbols | std::views::values | std::views::join | - std::views::filter([](auto Symbol) - { return Symbol->IsParameter(); }) | - std::views::transform([](auto Symbol) - { return std::static_pointer_cast(Symbol); }) | + return Symbols | + std::views::values | + std::views::join | + std::views::filter([](auto Symbol) { return Symbol->IsParameter(); }) | + std::views::transform([](auto Symbol) { return static_cast(Symbol); }) | std::ranges::to(); } -std::vector> BoundScope::DeclaredSymbols() const noexcept +std::vector BoundScope::DeclaredSymbols() const noexcept { - return Symbols | std::views::values | std::views::join | std::ranges::to(); + return Symbols | + std::views::values | + std::views::join | + std::ranges::to(); } diff --git a/src/Mamba/Code Analysis/Binding/BoundScope.h b/src/Mamba/Code Analysis/Binding/BoundScope.h index a6bbef2..4f7e61b 100644 --- a/src/Mamba/Code Analysis/Binding/BoundScope.h +++ b/src/Mamba/Code Analysis/Binding/BoundScope.h @@ -1,10 +1,14 @@ #pragma once -#include #include #include +#include "FunctionSymbol.h" #include "MambaCore.h" +#include "ParameterSymbol.h" +#include "Symbol.h" +#include "TypeSymbol.h" +#include "VariableSymbol.h" namespace Mamba { @@ -12,33 +16,30 @@ namespace Mamba // Function symbols with the same name form an overload set. However, when the multi non-function symbols with the // same name were found during name lookup, the name is ambiguous and the program is ill-formed, diagnostics are // required. - class BoundScope : public std::enable_shared_from_this + class BoundScope { - std::unordered_map>> Symbols; + std::unordered_map> Symbols; public: - [[nodiscard]] BoundScope(const NullableSharedPtr Parent) noexcept; - - void Declare(const std::shared_ptr Symbol) noexcept; - std::shared_ptr DeclareScope() noexcept; - - std::vector> LookupVariable(const std::shared_ptr Name) const noexcept; - std::vector> LookupFunction(const std::shared_ptr Name - ) const noexcept; - std::vector> LookupType(const std::shared_ptr Name - ) const noexcept; - std::vector> LookupParameter(const std::shared_ptr Name - ) const noexcept; - std::vector> Lookup(const std::shared_ptr Name - ) const noexcept; - - std::vector> DeclaredVariables() const noexcept; - std::vector> DeclaredFunctions() const noexcept; - std::vector> DeclaredTypes() const noexcept; - std::vector> DeclaredParameters() const noexcept; - std::vector> DeclaredSymbols() const noexcept; - - NullableSharedPtr Parent; - std::vector> Children; + [[nodiscard]] BoundScope(NullablePointer Parent) noexcept; + ~BoundScope() noexcept; + + void Declare(const Symbol* Symbol) noexcept; + BoundScope* DeclareScope() noexcept; + + std::vector LookupVariable(StringView Name) const noexcept; + std::vector LookupFunction(StringView Name) const noexcept; + std::vector LookupType(StringView Name) const noexcept; + std::vector LookupParameter(StringView Name) const noexcept; + std::vector Lookup(const StringView) const noexcept; + + std::vector DeclaredVariables() const noexcept; + std::vector DeclaredFunctions() const noexcept; + std::vector DeclaredTypes() const noexcept; + std::vector DeclaredParameters() const noexcept; + std::vector DeclaredSymbols() const noexcept; + + NullablePointer Parent; + std::vector Children; }; }; // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundStatement.cpp b/src/Mamba/Code Analysis/Binding/BoundStatement.cpp index 8bccfef..332b32b 100644 --- a/src/Mamba/Code Analysis/Binding/BoundStatement.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundStatement.cpp @@ -2,4 +2,5 @@ using namespace Mamba; -BoundStatement::BoundStatement(const std::shared_ptr Syntax) noexcept : Super(Syntax) {} \ No newline at end of file +BoundStatement::BoundStatement(const SyntaxNode* Syntax) noexcept : + Super(Syntax) {} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundStatement.h b/src/Mamba/Code Analysis/Binding/BoundStatement.h index 8f379ca..d692e69 100644 --- a/src/Mamba/Code Analysis/Binding/BoundStatement.h +++ b/src/Mamba/Code Analysis/Binding/BoundStatement.h @@ -2,7 +2,6 @@ #include "BoundNode.h" #include "SyntaxNode.h" -#include namespace Mamba { @@ -11,6 +10,6 @@ namespace Mamba public: using Super = BoundNode; - [[nodiscard]] BoundStatement(const std::shared_ptr Syntax) noexcept; + [[nodiscard]] BoundStatement(const SyntaxNode* Syntax) noexcept; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundUnaryExpression.cpp b/src/Mamba/Code Analysis/Binding/BoundUnaryExpression.cpp index 563cb72..1a1c53b 100644 --- a/src/Mamba/Code Analysis/Binding/BoundUnaryExpression.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundUnaryExpression.cpp @@ -1,30 +1,35 @@ #include "BoundUnaryExpression.h" -#include "BoundConstant.h" #include "ConstantFolding.h" +#include "TypeSymbol.h" using namespace Mamba; BoundUnaryExpression::BoundUnaryExpression( - const std::shared_ptr Syntax, + const SyntaxNode* Syntax, const BoundUnaryOperator& Operator, - const std::shared_ptr Operand + const BoundExpression* Operand ) noexcept : Super(Syntax), Operator(Operator), Operand(Operand) { } +BoundUnaryExpression::~BoundUnaryExpression() noexcept +{ + delete Operand; +} + BoundNodeKind BoundUnaryExpression::Kind() const noexcept { return BoundNodeKind::UnaryExpression; } -std::shared_ptr BoundUnaryExpression::Type() const noexcept +const TypeSymbol* BoundUnaryExpression::Type() const noexcept { return Operand->Type(); } -NullableSharedPtr BoundUnaryExpression::ConstantValue() const noexcept +Constant BoundUnaryExpression::ConstantValue() const noexcept { return ConstantFolding::Fold(Operator, Operand); } \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundUnaryExpression.h b/src/Mamba/Code Analysis/Binding/BoundUnaryExpression.h index e2bca89..a1d9cf9 100644 --- a/src/Mamba/Code Analysis/Binding/BoundUnaryExpression.h +++ b/src/Mamba/Code Analysis/Binding/BoundUnaryExpression.h @@ -1,10 +1,8 @@ #pragma once -#include - #include "BoundExpression.h" #include "BoundNodeKind.h" -#include "MambaCore.h" +#include "BoundUnaryOperator.h" namespace Mamba { @@ -14,16 +12,18 @@ namespace Mamba using Super = BoundExpression; [[nodiscard]] BoundUnaryExpression( - const std::shared_ptr Syntax, - const class BoundUnaryOperator& Operator, - const std::shared_ptr Operand + const SyntaxNode* Syntax, + const BoundUnaryOperator& Operator, + const BoundExpression* Operand ) noexcept; + ~BoundUnaryExpression() noexcept override; + BoundNodeKind Kind() const noexcept override; - std::shared_ptr Type() const noexcept override; - NullableSharedPtr ConstantValue() const noexcept override; + const TypeSymbol* Type() const noexcept override; + Constant ConstantValue() const noexcept override; - const class BoundUnaryOperator& Operator; - const std::shared_ptr Operand; + const BoundUnaryOperator& Operator; + const BoundExpression* Operand; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundUnaryOperator.cpp b/src/Mamba/Code Analysis/Binding/BoundUnaryOperator.cpp index ba11004..9fc8bee 100644 --- a/src/Mamba/Code Analysis/Binding/BoundUnaryOperator.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundUnaryOperator.cpp @@ -2,48 +2,30 @@ #include -#include "BoundUnaryOperatorKind.h" -#include "MambaCore.h" -#include "SyntaxKind.h" -#include "TypeSymbol.h" - using namespace Mamba; -BoundUnaryOperator::BoundUnaryOperator( - const enum SyntaxKind SyntaxKind, - const BoundUnaryOperatorKind Kind, - const std::shared_ptr OperandType -) noexcept : - SyntaxKind(SyntaxKind), Kind(Kind), OperandType(OperandType) +BoundUnaryOperator::BoundUnaryOperator(SyntaxKind Kind, const BoundUnaryOperatorKind BoundKind, const TypeSymbol* OperandType) noexcept : + Kind(Kind), BoundKind(BoundKind), OperandType(OperandType) { } -BoundUnaryOperator::BoundUnaryOperator( - const enum SyntaxKind SyntaxKind, - const BoundUnaryOperatorKind Kind, - const std::shared_ptr OperandType, - const std::shared_ptr ResultType -) noexcept : - SyntaxKind(SyntaxKind), Kind(Kind), OperandType(OperandType), ResultType(ResultType) {}; +BoundUnaryOperator::BoundUnaryOperator(SyntaxKind Kind, const BoundUnaryOperatorKind BoundKind, const TypeSymbol* OperandType, const TypeSymbol* ResultType) noexcept : + Kind(Kind), BoundKind(BoundKind), OperandType(OperandType), ResultType(ResultType) {}; BoundUnaryOperator BoundUnaryOperator::Operators[]{ - BoundUnaryOperator(SyntaxKind::BangToken, BoundUnaryOperatorKind::LogicalNegation, TypeSymbol::Bool), + BoundUnaryOperator(SyntaxKind::BangToken, BoundUnaryOperatorKind::LogicalNegation, &TypeSymbol::Bool), - BoundUnaryOperator(SyntaxKind::PlusToken, BoundUnaryOperatorKind::Identity, TypeSymbol::Int), - BoundUnaryOperator(SyntaxKind::MinusToken, BoundUnaryOperatorKind::Negation, TypeSymbol::Int), - BoundUnaryOperator(SyntaxKind::TildeToken, BoundUnaryOperatorKind::OnesComplement, TypeSymbol::Int) + BoundUnaryOperator(SyntaxKind::PlusToken, BoundUnaryOperatorKind::Identity, &TypeSymbol::Int), + BoundUnaryOperator(SyntaxKind::MinusToken, BoundUnaryOperatorKind::Negation, &TypeSymbol::Int), + BoundUnaryOperator(SyntaxKind::TildeToken, BoundUnaryOperatorKind::OnesComplement, &TypeSymbol::Int) }; -NullablePointer BoundUnaryOperator::Bind( - const enum SyntaxKind SyntaxKind, - const std::shared_ptr OperandType -) noexcept +NullablePointer BoundUnaryOperator::Bind(SyntaxKind Kind, const TypeSymbol* OperandType) noexcept { - const auto Result = std::ranges::find_if( + auto Result = std::ranges::find_if( std::ranges::begin(Operators), std::ranges::end(Operators), - [=](const BoundUnaryOperator& Operator) - { return Operator.SyntaxKind == SyntaxKind && Operator.OperandType == OperandType; } + [=](auto Operator) { return Operator.Kind == Kind && Operator.OperandType == OperandType; } ); if (Result == std::ranges::end(Operators)) { diff --git a/src/Mamba/Code Analysis/Binding/BoundUnaryOperator.h b/src/Mamba/Code Analysis/Binding/BoundUnaryOperator.h index 8a5612d..058651b 100644 --- a/src/Mamba/Code Analysis/Binding/BoundUnaryOperator.h +++ b/src/Mamba/Code Analysis/Binding/BoundUnaryOperator.h @@ -1,40 +1,28 @@ #pragma once -#include - #include "BoundUnaryOperatorKind.h" #include "MambaCore.h" #include "SyntaxKind.h" +#include "TypeSymbol.h" namespace Mamba { class BoundUnaryOperator { - [[nodiscard]] BoundUnaryOperator( - const SyntaxKind SyntaxKind, - const BoundUnaryOperatorKind Kind, - const std::shared_ptr OperandType - ) noexcept; - - [[nodiscard]] BoundUnaryOperator( - const SyntaxKind SyntaxKind, - const BoundUnaryOperatorKind Kind, - const std::shared_ptr OperandType, - const std::shared_ptr ResultType - ) noexcept; + [[nodiscard]] BoundUnaryOperator(SyntaxKind Kind, BoundUnaryOperatorKind BoundKind, const TypeSymbol* OperandType) noexcept; + [[nodiscard]] BoundUnaryOperator(SyntaxKind Kind, BoundUnaryOperatorKind BoundKind, const TypeSymbol* OperandType, const TypeSymbol* ResultType) noexcept; public: - const enum SyntaxKind SyntaxKind; - const BoundUnaryOperatorKind Kind; - const std::shared_ptr OperandType; - const std::shared_ptr ResultType; + SyntaxKind Kind; + BoundUnaryOperatorKind BoundKind; + const TypeSymbol* OperandType; + const TypeSymbol* ResultType; private: static BoundUnaryOperator Operators[]; public: // when the return value is not null, the life time of the object lasts to the end of the program - static NullablePointer - Bind(const enum SyntaxKind SyntaxKind, const std::shared_ptr OperandType) noexcept; + static NullablePointer Bind(SyntaxKind Kind, const TypeSymbol* OperandType) noexcept; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundVariableDeclaration.cpp b/src/Mamba/Code Analysis/Binding/BoundVariableDeclaration.cpp index 59fc242..f921ee3 100644 --- a/src/Mamba/Code Analysis/Binding/BoundVariableDeclaration.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundVariableDeclaration.cpp @@ -3,14 +3,19 @@ using namespace Mamba; BoundVariableDeclaration::BoundVariableDeclaration( - const std::shared_ptr Syntax, - const std::shared_ptr Variable, - const std::shared_ptr Initializer + const SyntaxNode* Syntax, + const VariableSymbol* Variable, + const BoundExpression* Initializer ) noexcept : Super(Syntax), Variable(Variable), Initializer(Initializer) { } +BoundVariableDeclaration::~BoundVariableDeclaration() noexcept +{ + delete Initializer; +} + BoundNodeKind BoundVariableDeclaration::Kind() const noexcept { return BoundNodeKind::VariableDeclaration; diff --git a/src/Mamba/Code Analysis/Binding/BoundVariableDeclaration.h b/src/Mamba/Code Analysis/Binding/BoundVariableDeclaration.h index a0e38ec..1d03ee6 100644 --- a/src/Mamba/Code Analysis/Binding/BoundVariableDeclaration.h +++ b/src/Mamba/Code Analysis/Binding/BoundVariableDeclaration.h @@ -1,8 +1,8 @@ #pragma once -#include - +#include "BoundExpression.h" #include "BoundStatement.h" +#include "VariableSymbol.h" namespace Mamba { @@ -12,14 +12,16 @@ namespace Mamba using Super = BoundStatement; [[nodiscard]] BoundVariableDeclaration( - const std::shared_ptr Syntax, - const std::shared_ptr Variable, - const std::shared_ptr Initializer + const SyntaxNode* Syntax, + const VariableSymbol* Variable, + const BoundExpression* Initializer ) noexcept; + ~BoundVariableDeclaration() noexcept override; + BoundNodeKind Kind() const noexcept override; - const std::shared_ptr Variable; - const std::shared_ptr Initializer; + const VariableSymbol* Variable; + const BoundExpression* Initializer; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundVariableExpression.cpp b/src/Mamba/Code Analysis/Binding/BoundVariableExpression.cpp index e7cb221..4d904a1 100644 --- a/src/Mamba/Code Analysis/Binding/BoundVariableExpression.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundVariableExpression.cpp @@ -4,10 +4,7 @@ using namespace Mamba; -BoundVariableExpression::BoundVariableExpression( - const std::shared_ptr Syntax, - const std::shared_ptr Variable -) noexcept : +BoundVariableExpression::BoundVariableExpression(const SyntaxNode* Syntax, const VariableSymbol* Variable) noexcept : Super(Syntax), Variable(Variable) { } @@ -17,7 +14,7 @@ BoundNodeKind BoundVariableExpression::Kind() const noexcept return BoundNodeKind::VariableExpression; } -std::shared_ptr BoundVariableExpression::Type() const noexcept +const TypeSymbol* BoundVariableExpression::Type() const noexcept { return Variable->Type; } diff --git a/src/Mamba/Code Analysis/Binding/BoundVariableExpression.h b/src/Mamba/Code Analysis/Binding/BoundVariableExpression.h index edfd690..886080f 100644 --- a/src/Mamba/Code Analysis/Binding/BoundVariableExpression.h +++ b/src/Mamba/Code Analysis/Binding/BoundVariableExpression.h @@ -1,8 +1,7 @@ #pragma once -#include - #include "BoundExpression.h" +#include "VariableSymbol.h" namespace Mamba { @@ -12,13 +11,13 @@ namespace Mamba using Super = BoundExpression; [[nodiscard]] BoundVariableExpression( - const std::shared_ptr Syntax, - const std::shared_ptr Variable + const SyntaxNode* Syntax, + const VariableSymbol* Variable ) noexcept; BoundNodeKind Kind() const noexcept override; - virtual std::shared_ptr Type() const noexcept override; + const TypeSymbol* Type() const noexcept override; - const std::shared_ptr Variable; + const VariableSymbol* Variable; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/BoundWhileStatement.cpp b/src/Mamba/Code Analysis/Binding/BoundWhileStatement.cpp index 8aa913b..b36f05b 100644 --- a/src/Mamba/Code Analysis/Binding/BoundWhileStatement.cpp +++ b/src/Mamba/Code Analysis/Binding/BoundWhileStatement.cpp @@ -5,14 +5,20 @@ using namespace Mamba; BoundWhileStatement::BoundWhileStatement( - const std::shared_ptr SyntaxNode, - const std::shared_ptr Condition, - const std::shared_ptr Body + const SyntaxNode* SyntaxNode, + const BoundExpression* Condition, + const BoundStatement* Body ) noexcept : Super(SyntaxNode), Condition(Condition), Body(Body) { } +BoundWhileStatement::~BoundWhileStatement() noexcept +{ + delete Condition; + delete Body; +} + BoundNodeKind BoundWhileStatement::Kind() const noexcept { return BoundNodeKind::WhileStatement; diff --git a/src/Mamba/Code Analysis/Binding/BoundWhileStatement.h b/src/Mamba/Code Analysis/Binding/BoundWhileStatement.h index 50959cd..afa3b47 100644 --- a/src/Mamba/Code Analysis/Binding/BoundWhileStatement.h +++ b/src/Mamba/Code Analysis/Binding/BoundWhileStatement.h @@ -1,7 +1,6 @@ #pragma once -#include - +#include "BoundExpression.h" #include "BoundNodeKind.h" #include "BoundStatement.h" @@ -13,14 +12,16 @@ namespace Mamba using Super = BoundStatement; [[nodiscard]] BoundWhileStatement( - const std::shared_ptr SyntaxNode, - const std::shared_ptr Condition, - const std::shared_ptr Body + const SyntaxNode* SyntaxNode, + const BoundExpression* Condition, + const BoundStatement* Body ) noexcept; + ~BoundWhileStatement() noexcept override; + BoundNodeKind Kind() const noexcept override; - const std::shared_ptr Condition; - const std::shared_ptr Body; + const BoundExpression* Condition; + const BoundStatement* Body; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/ConstantFolding.cpp b/src/Mamba/Code Analysis/Binding/ConstantFolding.cpp index c3cdbd7..8b6fdf9 100644 --- a/src/Mamba/Code Analysis/Binding/ConstantFolding.cpp +++ b/src/Mamba/Code Analysis/Binding/ConstantFolding.cpp @@ -1,41 +1,36 @@ #include "ConstantFolding.h" -#include "BoundBinaryOperatorKind.h" -#include "BoundConstant.h" -#include "Literal.h" -#include "TypeSymbol.h" - using namespace Mamba; -NullableSharedPtr ConstantFolding::Fold( +Constant ConstantFolding::Fold( const BoundUnaryOperator& Operator, - const std::shared_ptr Operand + const BoundExpression* Operand ) { - if (!Operand->ConstantValue()) + if (!Operand->ConstantValue().IsValid()) { return {}; } - switch (Operator.Kind) + switch (Operator.BoundKind) { case BoundUnaryOperatorKind::Identity: return Operand->ConstantValue(); case BoundUnaryOperatorKind::Negation: - return std::make_shared(Literal::Negative(*Operand->ConstantValue()->Value)); + return -Operand->ConstantValue(); case BoundUnaryOperatorKind::LogicalNegation: - return std::make_shared(Literal::LogicalNegative(*Operand->ConstantValue()->Value)); + return !Operand->ConstantValue(); case BoundUnaryOperatorKind::OnesComplement: - return std::make_shared(Literal::OnesComplement(*Operand->ConstantValue()->Value)); + return ~Operand->ConstantValue(); default: return {}; } } -NullableSharedPtr ConstantFolding::Fold( - const std::shared_ptr& Left, +Constant ConstantFolding::Fold( + const BoundExpression* Left, const BoundBinaryOperator& Operator, - const std::shared_ptr Right + const BoundExpression* Right ) noexcept { const auto LeftConstant = Left->ConstantValue(); @@ -44,82 +39,62 @@ NullableSharedPtr ConstantFolding::Fold( // Special case && and || because there are cases where only one // side needs to be known. - if (Operator.Kind == BoundBinaryOperatorKind::LogicalAnd) + if (Operator.BoundKind == BoundBinaryOperatorKind::LogicalAnd) { - if ((LeftConstant && !(*LeftConstant)->BooleanValue) // Wrap - || (RightConstant && !(*RightConstant)->BooleanValue)) + if ((LeftConstant.IsValid() && !LeftConstant.Get()) || + (RightConstant.IsValid() && !RightConstant.Get())) { - return std::make_shared(std::make_shared(false)); + return false; } } - if (Operator.Kind == BoundBinaryOperatorKind::LogicalOr) + if (Operator.BoundKind == BoundBinaryOperatorKind::LogicalOr) { - if ((LeftConstant && (*LeftConstant)->BooleanValue) // Wrap - || (RightConstant && (*RightConstant)->BooleanValue)) + if ((LeftConstant.IsValid() && LeftConstant.Get()) || + (RightConstant.IsValid() && RightConstant.Get())) { - return std::make_shared(std::make_shared(true)); + return true; } } - if (!LeftConstant || !RightConstant) + if (!LeftConstant.IsValid() || !RightConstant.IsValid()) { return {}; } - const auto LeftValue = LeftConstant->Value; - const auto RightValue = RightConstant->Value; - - switch (Operator.Kind) + switch (Operator.BoundKind) { case BoundBinaryOperatorKind::Addition: - if (Left->Type() == TypeSymbol::Int || Left->Type() == TypeSymbol::String) - { - return std::make_shared(*LeftValue + *RightValue); - } - [[fallthrough]]; + return LeftConstant + RightConstant; case BoundBinaryOperatorKind::Subtraction: - if (Left->Type() == TypeSymbol::Int) - { - return std::make_shared(*LeftValue - *RightValue); - } - [[fallthrough]]; + return LeftConstant - RightConstant; case BoundBinaryOperatorKind::Multiplication: - if (Left->Type() == TypeSymbol::Int) - { - return std::make_shared(*LeftValue * *RightValue); - } - [[fallthrough]]; + return LeftConstant * RightConstant; case BoundBinaryOperatorKind::Division: - if (Left->Type() == TypeSymbol::Int) - { - return std::make_shared(*LeftValue / *RightValue); - } - [[fallthrough]]; + return LeftConstant / RightConstant; case BoundBinaryOperatorKind::LogicalAnd: - return std::make_shared(*LeftValue && *RightValue); + return LeftConstant && RightConstant; case BoundBinaryOperatorKind::LogicalOr: - return std::make_shared(*LeftValue || *RightValue); + return LeftConstant || RightConstant; case BoundBinaryOperatorKind::BitwiseAnd: - return std::make_shared(*LeftValue & *RightValue); + return LeftConstant & RightConstant; case BoundBinaryOperatorKind::BitwiseOr: - return std::make_shared(*LeftValue | *RightValue); + return LeftConstant | RightConstant; case BoundBinaryOperatorKind::BitwiseXor: - return std::make_shared(*LeftValue ^ *RightValue); + return LeftConstant ^ RightConstant; case BoundBinaryOperatorKind::Equals: - return std::make_shared(*LeftValue == *RightValue); + return LeftConstant == RightConstant; case BoundBinaryOperatorKind::NotEquals: - return std::make_shared(*LeftValue != *RightValue); + return LeftConstant != RightConstant; case BoundBinaryOperatorKind::Less: - return std::make_shared(*LeftValue < *RightValue); + return LeftConstant < RightConstant; case BoundBinaryOperatorKind::LessOrEquals: - return std::make_shared(*LeftValue <= *RightValue); + return LeftConstant <= RightConstant; case BoundBinaryOperatorKind::Greater: - return std::make_shared(*LeftValue > *RightValue); + return LeftConstant > RightConstant; case BoundBinaryOperatorKind::GreaterOrEquals: - return std::make_shared(*LeftValue >= *RightValue); + return LeftConstant >= RightConstant; } - std::unreachable(); return {}; } \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/ConstantFolding.h b/src/Mamba/Code Analysis/Binding/ConstantFolding.h index 0ac0cff..dade475 100644 --- a/src/Mamba/Code Analysis/Binding/ConstantFolding.h +++ b/src/Mamba/Code Analysis/Binding/ConstantFolding.h @@ -1,10 +1,6 @@ #pragma once -#include - #include "BoundBinaryOperator.h" -#include "MambaCore.h" - #include "BoundExpression.h" #include "BoundUnaryOperator.h" @@ -16,13 +12,15 @@ namespace Mamba ~ConstantFolding() = delete; public: - static NullableSharedPtr - Fold(const BoundUnaryOperator& Operator, const std::shared_ptr Operand); + static Constant Fold( + const BoundUnaryOperator& Operator, + const BoundExpression* Operand + ); - static NullableSharedPtr Fold( - const std::shared_ptr& Left, + static Constant Fold( + const BoundExpression* Left, const BoundBinaryOperator& Operator, - const std::shared_ptr Right + const BoundExpression* Right ) noexcept; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Binding/ScopeGuard.cpp b/src/Mamba/Code Analysis/Binding/ScopeGuard.cpp index a230dbe..23d0e2a 100644 --- a/src/Mamba/Code Analysis/Binding/ScopeGuard.cpp +++ b/src/Mamba/Code Analysis/Binding/ScopeGuard.cpp @@ -1,12 +1,12 @@ #include "ScopeGuard.h" -#include "BoundScope.h" - using namespace Mamba; -ScopeGuard::ScopeGuard(std::shared_ptr& Scope) noexcept : +ScopeGuard::ScopeGuard(BoundScope*& Scope) noexcept : Scope(Scope), Leaved() { + // The result of Scope.DeclareScope() is the child scope of the current scope, + // which is deleted when the parent scope is deconstructed. Scope = Scope->DeclareScope(); } @@ -24,6 +24,7 @@ void ScopeGuard::PreLeave() noexcept { // The parent of the scope is constructed in the constructor, // which is guaranteed to be non-const here. - Scope = std::const_pointer_cast(Scope->Parent); + Scope = const_cast(Scope->Parent); + Leaved = true; } diff --git a/src/Mamba/Code Analysis/Binding/ScopeGuard.h b/src/Mamba/Code Analysis/Binding/ScopeGuard.h index 4b1516a..bf674e4 100644 --- a/src/Mamba/Code Analysis/Binding/ScopeGuard.h +++ b/src/Mamba/Code Analysis/Binding/ScopeGuard.h @@ -1,17 +1,17 @@ #pragma once -#include +#include "BoundScope.h" namespace Mamba { // Creates a scope from the current scope and enters it on construction, and exits it on destruction. class ScopeGuard { - std::shared_ptr& Scope; + BoundScope*& Scope; bool Leaved : 1; public: - [[nodiscard]] ScopeGuard(std::shared_ptr& Scope) noexcept; + [[nodiscard]] ScopeGuard(BoundScope*& Scope) noexcept; ~ScopeGuard() noexcept; void PreLeave() noexcept; diff --git a/src/Mamba/Code Analysis/Compilation.cpp b/src/Mamba/Code Analysis/Compilation.cpp deleted file mode 100644 index 91feda8..0000000 --- a/src/Mamba/Code Analysis/Compilation.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "Compilation.h" - -#include - -#include -#include - -#include "Binder.h" -#include "BoundCompilationUnit.h" -#include "BoundProgram.h" -#include "CompilationUnitSyntax.h" -#include "DotNet/DotNetEmitter.h" -#include "MambaCore.h" -#include "Parser.h" -#include "SourceText.h" -#include "SyntaxTree.h" - -namespace Mamba -{ - std::vector> TransformToSource(const std::vector& Sources) noexcept - { - auto SourceTexts = std::vector>(); - SourceTexts.reserve(Sources.size()); - for (auto&& Source : Sources) - { - const auto SharedSource = std::make_shared(Source); - SourceTexts.emplace_back(std::make_shared(SharedSource)); - } - return SourceTexts; - } - - std::shared_ptr Compilation::Compile(const std::shared_ptr SyntaxTree) noexcept - { - auto Parser = ::Mamba::Parser(SyntaxTree); - SyntaxTree->PrivateRoot = Parser.ParseCompilationUnit(); - SyntaxTree->PrivateDiagnostics = std::move(Parser.Diagnostics); - - fast_io::io::println(fast_io::mnp::code_cvt(SyntaxTree->Root()->ToString())); - - auto Binder = ::Mamba::Binder(SyntaxTree); - return Binder.BindCompilationUnit(); - } - - void Compilation::Compile(const StringView ModuleName) noexcept - { - auto CompilationUnits = std::vector>(); - for (auto&& SyntaxTree : SyntaxTrees) - { - CompilationUnits.emplace_back(Compilation::Compile(SyntaxTree)); - } - - auto Emitter = DotNetEmitter(); - const auto BoundProgram = ::Mamba::BoundProgram(CompilationUnits); - Emitter.Emit(BoundProgram, ModuleName); - } - - std::vector Compilation::Diagnostics() const noexcept - { - return SyntaxTrees | - std::views::transform([](auto&& SyntaxTree) - { return SyntaxTree->PrivateDiagnostics; }) | - std::views::join | std::ranges::to(); - } - - Compilation::Compilation(const std::vector& Sources) noexcept : - Compilation(TransformToSource(Sources)) - { - } - - Compilation::Compilation(const std::vector>& SourceTexts) noexcept - { - for (auto&& SourceText : SourceTexts) - { - const auto SyntaxTree = std::make_shared<::Mamba::SyntaxTree>(SourceText); - SyntaxTrees.emplace_back(SyntaxTree); - } - } -} // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Compilation.h b/src/Mamba/Code Analysis/Compilation.h deleted file mode 100644 index ffdc646..0000000 --- a/src/Mamba/Code Analysis/Compilation.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "MambaCore.h" -#include "SourceText.h" -#include - -namespace Mamba -{ - // - class Compilation final - { - public: - std::vector> SyntaxTrees; - - [[nodiscard]] Compilation(const std::vector& Sources) noexcept; - [[nodiscard]] Compilation(const std::vector>& Sources) noexcept; - - private: - static std::shared_ptr Compile(const std::shared_ptr SyntaxTree) noexcept; - - public: - void Compile(const StringView ModuleName) noexcept; - - std::vector Diagnostics() const noexcept; - }; -} // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Compiler.cpp b/src/Mamba/Code Analysis/Compiler.cpp new file mode 100644 index 0000000..25e9939 --- /dev/null +++ b/src/Mamba/Code Analysis/Compiler.cpp @@ -0,0 +1,116 @@ +#include "BoundCompilationUnit.h" +#include "DiagnosticPrinter.h" +#include "Lexer.h" +#include "LLVMBackend.h" +#include "MambaCore.h" + +#include "Binder.h" +#include "Colors.h" +#include "Compiler.h" +#include "fast_io.h" +#include "Parser.h" + +using namespace fast_io::io; +using namespace Mamba; + +void PrintDiagnostics(std::span Diagnostics) noexcept +{ + for (auto&& Diagnostic : Diagnostics) + { + fast_io::io::println(Diagnostic); + } + + if (!Diagnostics.empty()) + { + exit(0); + } +} + +void Compiler::PrivateAddSourceFile(const std::string_view FileName) noexcept +{ + try + { + const auto FileLoader = fast_io::native_file_loader(FileName); + + const auto Info = SourceTextInfo{ + .FileName = Concat(fast_io::mnp::code_cvt(FileName)), + .Text = String(FileLoader.begin(), FileLoader.end()) + }; + SourceTexts.emplace_back(Info); + } + catch (fast_io::error error) + { + perrln( + Color("error: ", Colors::BrightForegroundRed), + Color("error reading '", Colors::BrightForegroundWhite), + Color(FileName, Colors::BrightForegroundWhite), + Color("': ", Colors::BrightForegroundWhite), + Color(error, Colors::BrightForegroundWhite) + ); + } +} + +void Compiler::ReportNoInputFiles() noexcept +{ + perrln( + "mamba: ", + Color("error: ", Colors::BrightForegroundRed), + Color("no input files", Colors::BrightForegroundWhite) + ); +} + +Parser Parse(std::tuple Input) noexcept +{ + auto [SyntaxTree, Lexer] = Input; + auto Tokens = std::vector{}; + while (true) + { + auto Token = Lexer.Lex(); + if (Token.Kind() == SyntaxKind::WhitespaceToken) + { + continue; + } + + Tokens.emplace_back(Token); + if (Token.Kind() == SyntaxKind::EndOfFileToken) + { + break; + } + } + + PrintDiagnostics(Lexer.Diagnostics); + return Parser(&SyntaxTree, std::move(Tokens)); +} + +void Compiler::Compile() noexcept +{ + if (SourceTexts.empty()) + { + ReportNoInputFiles(); + return; + } + + auto SyntaxTrees = SourceTexts | std::views::transform([](auto&& SourceText) { return SyntaxTree(SourceText); }) | std::ranges::to(); + auto Lexers = SyntaxTrees | std::views::transform([](auto&& SyntaxTree) { return Lexer(&SyntaxTree); }) | std::ranges::to(); + auto Parsers = std::views::zip(SyntaxTrees, Lexers) | std::views::transform(Parse) | std::ranges::to(); + for (std::tuple Input : std::views::zip(SyntaxTrees, Parsers)) + { + auto&& [SyntaxTree, Parser] = Input; + SyntaxTree.PrivateRoot = Parser.ParseCompilationUnit(); + SyntaxTree.BuildParentsMap(*SyntaxTree.Root()); + PrintDiagnostics(Parser.Diagnostics); + } + auto Binders = SyntaxTrees | std::views::transform([](auto&& SyntaxTree) { return Binder(&SyntaxTree); }) | std::ranges::to(); + auto BoundCompilationUnits = Binders | std::views::transform([](auto&& Binder) { return Binder.BindCompilationUnit(); }) | std::ranges::to(); + for (auto&& Binder : Binders) + { + PrintDiagnostics(Binder.Diagnostics); + } + + for (auto&& BoundCompilationUnit : BoundCompilationUnits) + { + delete BoundCompilationUnit; + } + + LLVMBackend::GenerateCode(BoundCompilationUnits, "Main"); +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Compiler.h b/src/Mamba/Code Analysis/Compiler.h new file mode 100644 index 0000000..4b0830b --- /dev/null +++ b/src/Mamba/Code Analysis/Compiler.h @@ -0,0 +1,33 @@ +#pragma once + +#include "DiagnosticBag.h" +#include "SourceText.h" +#include "SyntaxTree.h" + +namespace Mamba +{ + class Compiler + { + std::vector SourceTexts; + DiagnosticBag Diagnostics; + + void PrivateAddSourceFile(const std::string_view FileName) noexcept; + void ReportNoInputFiles() noexcept; + + public: + template + void AddSourceFile(const std::basic_string_view FileName) noexcept + { + if constexpr (std::is_same_v) + { + PrivateAddSourceFile(FileName); + } + else + { + PrivateAddSourceFile(fast_io::concat(fast_io::mnp::code_cvt(FileName))); + } + } + + void Compile() noexcept; + }; +} // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Diagnostic.cpp b/src/Mamba/Code Analysis/Diagnostic.cpp new file mode 100644 index 0000000..a153d9f --- /dev/null +++ b/src/Mamba/Code Analysis/Diagnostic.cpp @@ -0,0 +1,21 @@ +#include "Diagnostic.h" +#include "TextLine.h" + +using namespace Mamba; + +std::size_t Diagnostic::LineNumber() const noexcept +{ + return Location.StartLine() + 1; +} + +const TextLine& Diagnostic::Line() const noexcept +{ + auto LineIndex = Location.StartLine(); + return Location.Text.Lines()[LineIndex]; +} + +StringView Diagnostic::LineView() const noexcept +{ + auto CurrentLine = Line(); + return Location.Text.SubView(CurrentLine.Start, CurrentLine.Length); +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Diagnostic.h b/src/Mamba/Code Analysis/Diagnostic.h index 5607def..7767936 100644 --- a/src/Mamba/Code Analysis/Diagnostic.h +++ b/src/Mamba/Code Analysis/Diagnostic.h @@ -3,7 +3,6 @@ #include "MambaCore.h" #include "TextLocation.h" -#include namespace Mamba { @@ -19,5 +18,11 @@ namespace Mamba DiagnosticSeverity Severity; TextLocation Location; String Message; + + std::size_t LineNumber() const noexcept; + const TextLine& Line() const noexcept; + StringView LineView() const noexcept; + + StringView FileName() const noexcept; }; } // namespace Mamba diff --git a/src/Mamba/Code Analysis/DiagnosticBag.cpp b/src/Mamba/Code Analysis/DiagnosticBag.cpp index 4a10c0f..5e826c1 100644 --- a/src/Mamba/Code Analysis/DiagnosticBag.cpp +++ b/src/Mamba/Code Analysis/DiagnosticBag.cpp @@ -36,32 +36,32 @@ namespace Mamba void DiagnosticBag::ReportInvalidCharacter(const TextLocation Location, const Char Character) noexcept { - ReportError(Location, TEXT("Invalid character '"), Character, TEXT("'.")); + ReportError(Location, TEXT("无效字符 '"), fast_io::mnp::chvw(Character), TEXT("'.")); } void DiagnosticBag::ReportUnterminatedString(const TextLocation Location) noexcept { - ReportError(Location, TEXT("Unterminated string literal.")); + ReportError(Location, TEXT("未结束的字符串字面量")); } void DiagnosticBag::ReportInvalidDecimal(const TextLocation Location, const StringView Literal) noexcept { - ReportError(Location, Concat(TEXT("Invalid decimal number '"), Literal, TEXT("'."))); + ReportError(Location, Concat(TEXT("无效十进制字面量 '"), Literal, TEXT("'."))); } void DiagnosticBag::ReportInvalidHexadecimal(const TextLocation Location, const StringView Literal) noexcept { - ReportError(Location, Concat(TEXT("Invalid hexadecimal number '"), Literal, TEXT("'."))); + ReportError(Location, Concat(TEXT("无效十六进制字面量 '"), Literal, TEXT("'."))); } void DiagnosticBag::ReportInvalidBinary(const TextLocation Location, const StringView Literal) noexcept { - ReportError(Location, Concat(TEXT("Invalid binary number '"), Literal, TEXT("'."))); + ReportError(Location, Concat(TEXT("无效二进制字面量 '"), Literal, TEXT("'."))); } void DiagnosticBag::ReportInvalidOctal(const TextLocation Location, const StringView Literal) noexcept { - ReportError(Location, Concat(TEXT("Invalid octal number '"), Literal, TEXT("'."))); + ReportError(Location, Concat(TEXT("无效八进制字面量 '"), Literal, TEXT("'."))); } void DiagnosticBag::ReportUnexpectedToken( @@ -71,50 +71,57 @@ namespace Mamba ) noexcept { // Unexpected token 'Kind', Expected: 'ExpectedKind'. - ReportError( - Location, - TEXT("Unexpected token '"), - SyntaxFacts::GetText(Kind), - TEXT("'"), - TEXT("Expected: '"), - SyntaxFacts::ToString(ExpectedKind), - TEXT("'.") - ); + if (ExpectedKind == SyntaxKind::IdentifierToken) + { + ReportError(Location, TEXT("此处应有标识符")); + } + else + { + ReportError( + Location, + TEXT("Unexpected token '"), + SyntaxFacts::ToString(Kind), + TEXT("' "), + TEXT("Expected: '"), + SyntaxFacts::ToString(ExpectedKind), + TEXT("'.") + ); + } } void DiagnosticBag::ReportDiscardExpressionValue(const TextLocation Location) noexcept { - ReportWarning(Location, TEXT("The result of the expression is discarded.")); + ReportWarning(Location, TEXT("表达式的结果被忽略")); } - void DiagnosticBag::ReportVariableAlreadyDeclared(const TextLocation Location, const StringView Name) noexcept + void DiagnosticBag::ReportVariableAlreadyDeclared(const TextLocation Location, StringView Name) noexcept { // Variable 'Name' is already declared, previous declaration at FileName:StartLine:StartCharacter. ReportError( Location, - TEXT("Variable '"), + TEXT("变量 '"), Name, - TEXT("' is already declared, previous declaration at "), - *Location.FileName(), + TEXT("' 已在此处声明过: "), + Location.FileName(), TEXT(":"), Location.StartLine(), TEXT(":"), - Location.StartCharacter() + Location.RelativeStartCharacter() ); } void DiagnosticBag::ReportUnreachableCode(const TextLocation Location) noexcept { - ReportWarning(Location, TEXT("Unreachable code.")); + ReportWarning(Location, TEXT("此处永远不会被执行")); } - void DiagnosticBag::ReportUnreachableCode(const std::shared_ptr Node) noexcept + void DiagnosticBag::ReportUnreachableCode(const SyntaxNode* Node) noexcept { switch (Node->Kind()) { case SyntaxKind::BlockStatement: { - const auto Statements = std::static_pointer_cast(Node)->Statements; + auto Statements = static_cast(Node)->Statements; if (!Statements.empty()) { ReportUnreachableCode(Statements.front()); @@ -123,37 +130,47 @@ namespace Mamba } case SyntaxKind::VariableDeclaration: - ReportUnreachableCode(std::static_pointer_cast(Node)->Keyword->Location()); + ReportUnreachableCode(static_cast(Node)->Keyword->Location()); return; case SyntaxKind::IfStatement: - ReportUnreachableCode(std::static_pointer_cast(Node)->IfKeyword->Location()); + ReportUnreachableCode(static_cast(Node)->IfKeyword->Location()); return; case SyntaxKind::WhileStatement: - ReportUnreachableCode(std::static_pointer_cast(Node)->WhileKeyword->Location()); + ReportUnreachableCode(static_cast(Node)->WhileKeyword->Location()); return; case SyntaxKind::DoWhileStatement: - ReportUnreachableCode(std::static_pointer_cast(Node)->WhileKeyword->Location()); + ReportUnreachableCode(static_cast(Node)->WhileKeyword->Location()); return; case SyntaxKind::ForStatement: - ReportUnreachableCode(std::static_pointer_cast(Node)->Keyword->Location()); + ReportUnreachableCode(static_cast(Node)->Keyword->Location()); return; case SyntaxKind::BreakStatement: - ReportUnreachableCode(std::static_pointer_cast(Node)->Keyword->Location()); + ReportUnreachableCode(static_cast(Node)->Keyword->Location()); return; case SyntaxKind::ContinueStatement: - ReportUnreachableCode(std::static_pointer_cast(Node)->Keyword->Location()); + ReportUnreachableCode(static_cast(Node)->Keyword->Location()); return; case SyntaxKind::ReturnStatement: - ReportUnreachableCode(std::static_pointer_cast(Node)->ReturnKeyword->Location()); + ReportUnreachableCode(static_cast(Node)->ReturnKeyword->Location()); return; case SyntaxKind::ExpressionStatement: - ReportUnreachableCode(std::static_pointer_cast(Node)->Expression->Location()); + ReportUnreachableCode(static_cast(Node)->Expression->Location()); return; case SyntaxKind::CallExpression: - ReportUnreachableCode(std::static_pointer_cast(Node)->Identifier->Location()); + ReportUnreachableCode(static_cast(Node)->Identifier->Location()); return; default: break; } } + + void DiagnosticBag::ReportUndeclaredIdentifier(TextLocation Location, StringView Name) noexcept + { + ReportError(Location, TEXT("未声明的标识符 '"), Name, TEXT("'.")); + } + + void DiagnosticBag::ReportAmbiguousIdentifier(TextLocation Location, StringView Name) noexcept + { + ReportError(Location, TEXT("标识符有歧义 '"), Name, TEXT("'.")); + } } // namespace Mamba diff --git a/src/Mamba/Code Analysis/DiagnosticBag.h b/src/Mamba/Code Analysis/DiagnosticBag.h index ee4ce4f..6fd90fa 100644 --- a/src/Mamba/Code Analysis/DiagnosticBag.h +++ b/src/Mamba/Code Analysis/DiagnosticBag.h @@ -1,10 +1,10 @@ #pragma once -#include #include #include "Diagnostic.h" #include "SyntaxKind.h" +#include "SyntaxNode.h" #include "TextLocation.h" namespace Mamba @@ -51,9 +51,12 @@ namespace Mamba ) noexcept; void ReportDiscardExpressionValue(const TextLocation Location) noexcept; - void ReportVariableAlreadyDeclared(const TextLocation Location, const StringView Name) noexcept; + void ReportVariableAlreadyDeclared(const TextLocation Location, StringView Name) noexcept; void ReportUnreachableCode(const TextLocation Location) noexcept; - void ReportUnreachableCode(const std::shared_ptr Node) noexcept; + void ReportUnreachableCode(const SyntaxNode* Node) noexcept; + + void ReportUndeclaredIdentifier(TextLocation Location, StringView Name) noexcept; + void ReportAmbiguousIdentifier(TextLocation Location, StringView Name) noexcept; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Emit/DotNet/DotNetEmitter.cpp b/src/Mamba/Code Analysis/Emit/DotNet/DotNetEmitter.cpp deleted file mode 100644 index a737d5d..0000000 --- a/src/Mamba/Code Analysis/Emit/DotNet/DotNetEmitter.cpp +++ /dev/null @@ -1,174 +0,0 @@ -#include "DotNetEmitter.h" -#include "BoundCallExpression.h" -#include "BoundConstant.h" -#include "BoundExpressionStatement.h" -#include "BoundNodeKind.h" -#include "BoundScope.h" -#include "DotNet/OpCodes.h" -#include "fast_io_core_impl/integers/impl.h" -#include "LinkIdentifier.h" -#include "ParameterSymbol.h" -#include "TypeSymbol.h" - -#include -#include - -#include - -using namespace Mamba; - -constexpr auto LinkerVersion = 1uz; - -std::vector DotNetEmitter::Emit(const BoundProgram& Program, const StringView ModuleName) noexcept -{ - fast_io::io::println("Linking ", fast_io::mnp::code_cvt(ModuleName)); - if (Program.CompilationUnits.empty()) - { - fast_io::io::perrln("error: no compilation units found"); - } - - Serializer.Write(LinkerVersion); - Serializer.Write(ModuleName); - for (auto&& CompilationUnit : Program.CompilationUnits) - { - EmitCompilationUnit(*CompilationUnit); - } - - ::fast_io::obuf_file file(::fast_io::concat(::fast_io::mnp::code_cvt(ModuleName))); - ::fast_io::write(file, Serializer.Data.begin(), Serializer.Data.end()); - - fast_io::io::perrln("Serialized data size: ", Serializer.Data.size()); - return {}; -} - -void DotNetEmitter::EmitCompilationUnit(const BoundCompilationUnit& CompilationUnit) noexcept -{ - EmitScope(*CompilationUnit.GlobalScope); -} - -void DotNetEmitter::EmitScope(const BoundScope& Scope) noexcept -{ - for (auto&& Symbol : Scope.DeclaredSymbols()) - { - switch (Symbol->Kind()) - { - case SymbolKind::Function: - EmitFunction(std::static_pointer_cast(Symbol)); - break; - case SymbolKind::Variable: - EmitVariable(*std::static_pointer_cast(Symbol)); - break; - case SymbolKind::Parameter: - case SymbolKind::Type: - default: -#ifdef DEBUG - fast_io::io::println("Unsupported symbol."); -#endif - break; - } - } - - for (auto&& Scope : Scope.Children) - { - EmitScope(*Scope); - } -} - -void DotNetEmitter::EmitVariable(const VariableSymbol& VariableSymbol) noexcept -{ - Serializer.Write(LinkIdentifier::Variable); - Serializer.Write(*VariableSymbol.Type->Name); - Serializer.Write(*VariableSymbol.Name); -} - -void DotNetEmitter::EmitFunction(const std::shared_ptr Function) noexcept -{ - Serializer.Write(LinkIdentifier::Function); - Serializer.Write(*Function->Type->Name); - Serializer.Write(*Function->Name); - Serializer.Write(Function->Parameters.size()); - for (auto&& Parameter : Function->Parameters) - { - Serializer.Write(*Parameter->Type->Name); - } - EmitStatement(*Function->BoundDeclaration->Body); -} - -void DotNetEmitter::EmitStatement(const BoundStatement& Statement) noexcept -{ - switch (Statement.Kind()) - { - case BoundNodeKind::ExpressionStatement: - EmitExpressionStatement(static_cast(Statement)); - break; - case BoundNodeKind::BlockStatement: - EmitBlockStatement(static_cast(Statement)); - break; - default: - fast_io::io::perrln("Unsupported statement: ", static_cast(Statement.Kind())); - break; - } -} - -void DotNetEmitter::EmitCallExpression(const BoundCallExpression& Expression) noexcept -{ - for (auto&& Argument : Expression.Arguments) - { - EmitExpression(*Argument); - } - - Serializer.Write(LinkIdentifier::Instruction); - Serializer.Write(DotNet::OpCodes::Call); - Serializer.Write(LinkIdentifier::String); - Serializer.Write(*Expression.Function->Name); -} - -void DotNetEmitter::EmitExpression(const BoundExpression& Expression) noexcept -{ - if (Expression.ConstantValue()) - { - EmitConstantExpression(Expression); - return; - } - - switch (Expression.Kind()) - { - case BoundNodeKind::CallExpression: - EmitCallExpression(static_cast(Expression)); - break; - default: - fast_io::io::perrln("Unsupported expression"); - } -} - -void DotNetEmitter::EmitExpressionStatement(const BoundExpressionStatement& Statement) noexcept -{ - EmitExpression(*Statement.Expression); - if (Statement.Expression->Type() != TypeSymbol::Void) - { - Serializer.Write(LinkIdentifier::Instruction); - Serializer.Write(DotNet::OpCodes::Pop); - } -} - -void DotNetEmitter::EmitConstantExpression(const BoundExpression& Expression) noexcept -{ - if (Expression.Type() == TypeSymbol::String) - { - Serializer.Write(LinkIdentifier::Instruction); - Serializer.Write(DotNet::OpCodes::Ldstr); - Serializer.Write(LinkIdentifier::String); - Serializer.Write(StringView(**Expression.ConstantValue()->Value->StringValue)); - return; - } - - fast_io::io::perrln("Unsupported constant expression"); -} - -void DotNetEmitter::EmitBlockStatement(const BoundBlockStatement& BlockStatement) -{ - for (auto&& Statement : BlockStatement.Statements) - { - EmitStatement(*Statement); - } -} diff --git a/src/Mamba/Code Analysis/Emit/DotNet/DotNetEmitter.h b/src/Mamba/Code Analysis/Emit/DotNet/DotNetEmitter.h deleted file mode 100644 index 57de4dc..0000000 --- a/src/Mamba/Code Analysis/Emit/DotNet/DotNetEmitter.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include "BoundBlockStatement.h" -#include "BoundCallExpression.h" -#include "BoundCompilationUnit.h" -#include "BoundExpression.h" -#include "BoundExpressionStatement.h" -#include "BoundNopStatement.h" -#include "BoundScope.h" -#include "DiagnosticBag.h" -#include "Emitter.h" -#include "FunctionSymbol.h" -#include "Serializer.h" -#include "VariableSymbol.h" - -namespace Mamba -{ - class DotNetEmitter final : public Emitter - { - DiagnosticBag Diagnostics; - ::Mamba::Serializer Serializer; - - public: - virtual std::vector Emit(const BoundProgram& Program, const StringView ModuleName) noexcept override; - - private: - void EmitCompilationUnit(const BoundCompilationUnit& CompilationUnit) noexcept; - void EmitScope(const BoundScope& Scope) noexcept; - void EmitVariable(const VariableSymbol& VariableSymbol) noexcept; - void EmitFunction(const std::shared_ptr Function) noexcept; - void EmitStatement(const BoundStatement& Statement) noexcept; - void EmitNopStatement(const BoundNopStatement& Statement) noexcept; - void EmitCallExpression(const BoundCallExpression& Expression) noexcept; - void EmitExpression(const BoundExpression& Expression) noexcept; - void EmitExpressionStatement(const BoundExpressionStatement& Statement) noexcept; - void EmitConstantExpression(const BoundExpression& Expression) noexcept; - void EmitBlockStatement(const BoundBlockStatement& BlockStatement); - }; -} // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Emit/DotNet/OpCodes.h b/src/Mamba/Code Analysis/Emit/DotNet/OpCodes.h deleted file mode 100644 index 863eebe..0000000 --- a/src/Mamba/Code Analysis/Emit/DotNet/OpCodes.h +++ /dev/null @@ -1,229 +0,0 @@ -#pragma once - -namespace Mamba -{ - namespace DotNet - { - enum class OpCodes - { - Add = 0x58, - AddOvf = 0xD6, - AddOvfUn = 0xD7, - And = 0x5F, - Arglist = 0xFE00, - Beq = 0x3B, - BeqS = 0x2E, - Bge = 0x3C, - BgeS = 0x2F, - BgeUn = 0x41, - BgeUnS = 0x34, - Bgt = 0x3D, - BgtS = 0x30, - BgtUn = 0x42, - BgtUnS = 0x35, - Ble = 0x3E, - BleS = 0x31, - BleUn = 0x43, - BleUnS = 0x36, - Blt = 0x3F, - BltS = 0x32, - BltUn = 0x44, - BltUnS = 0x37, - BneUn = 0x40, - BneUnS = 0x33, - Box = 0x8C, - Br = 0x38, - BrS = 0x2B, - Break = 0x01, - Brfalse = 0x39, - BrfalseS = 0x2C, - Brtrue = 0x3A, - BrtrueS = 0x2D, - Call = 0x28, - Calli = 0x29, - Callvirt = 0x6F, - Castclass = 0x74, - Ceq = 0xFF01, - Cgt = 0xFE02, - CgtUn = 0xFE03, - Ckfinite = 0xC3, - Clt = 0xFE04, - CltUn = 0xFE05, - Constrained = 0xFF16, - ConvI = 0xD3, - ConvI1 = 0x67, - ConvI2 = 0x68, - ConvI4 = 0x69, - ConvI8 = 0x6A, - ConvOvfI = 0xD4, - ConvOvfIUn = 0x8A, - ConvOvfI1 = 0xB3, - ConvOvfI1Un = 0x82, - ConvOvfI2 = 0xB5, - ConvOvfI2Un = 0x83, - ConvOvfI4 = 0xB7, - ConvOvfI4Un = 0x84, - ConvOvfI8 = 0xB9, - ConvOvfI8Un = 0x85, - ConvOvfU = 0xD5, - ConvOvfUUn = 0x8B, - ConvOvfU1 = 0xB4, - ConvOvfU1Un = 0x86, - ConvOvfU2 = 0xB6, - ConvOvfU2Un = 0x87, - ConvOvfU4 = 0xB8, - ConvOvfU4Un = 0x88, - ConvOvfU8 = 0xBA, - ConvOvfU8Un = 0x89, - ConvRUN = 0x76, - ConvR4 = 0x6B, - ConvR8 = 0x6C, - ConvU = 0xE0, - ConvU1 = 0xD2, - ConvU2 = 0xD1, - ConvU4 = 0x6D, - ConvU8 = 0x6E, - Cpblk = 0xFE17, - Cpobj = 0x70, - Div = 0x5B, - DivUn = 0x5C, - Dup = 0x25, - Endfilter = 0xFE11, - Endfinally = 0xDC, - Initblk = 0xFE18, - Initobj = 0xFE15, - Isinst = 0x75, - Jmp = 0x27, - Ldarg = 0xFE09, - Ldarg0 = 0x02, - Ldarg1 = 0x03, - Ldarg2 = 0x04, - Ldarg3 = 0x05, - LdargS = 0x0E, - Ldarga = 0xFE0A, - LdargaS = 0x0F, - LdcI4 = 0x20, - LdcI40 = 0x16, - LdcI41 = 0x17, - LdcI42 = 0x18, - LdcI43 = 0x19, - LdcI44 = 0x1A, - LdcI45 = 0x1B, - LdcI46 = 0x1C, - LdcI47 = 0x1D, - LdcI48 = 0x1E, - LdcI4M1 = 0x15, - LdcI4S = 0x1F, - LdcI8 = 0x21, - LdcR4 = 0x22, - LdcR8 = 0x23, - Ldelem = 0xA3, - LdelemI = 0x97, - LdelemI1 = 0x90, - LdelemI2 = 0x92, - LdelemI4 = 0x94, - LdelemI8 = 0x96, - LdelemR4 = 0x98, - LdelemR8 = 0x99, - LdelemRef = 0x9A, - LdelemU1 = 0x91, - LdelemU2 = 0x93, - LdelemU4 = 0x95, - Ldelema = 0x8F, - Ldfld = 0x7B, - Ldflda = 0x7C, - Ldftn = 0xFF06, - LdindI = 0x4D, - LdindI1 = 0x46, - LdindI2 = 0x48, - LdindI4 = 0x4A, - LdindI8 = 0x4C, - LdindR4 = 0x4E, - LdindR8 = 0x4F, - LdindRef = 0x50, - LdindU1 = 0x47, - LdindU2 = 0x49, - LdindU4 = 0x4B, - Ldlen = 0x8E, - Ldloc = 0xFE0C, - Ldloc0 = 0x06, - Ldloc1 = 0x07, - Ldloc2 = 0x08, - Ldloc3 = 0x09, - LdlocS = 0x11, - Ldloca = 0xFE0D, - LdlocaS = 0x12, - Ldnull = 0x14, - Ldobj = 0x71, - Ldsfld = 0x7E, - Ldsflda = 0x7F, - Ldstr = 0x72, - Ldtoken = 0xD0, - Ldvirtftn = 0xFF07, - Leave = 0xDD, - LeaveS = 0xDE, - Localloc = 0xFE0F, - Mkrefany = 0xC6, - Mul = 0x5A, - MulOvf = 0xD8, - MulOvfUn = 0xD9, - Neg = 0x65, - Newarr = 0x8D, - Newobj = 0x73, - Nop = 0x00, - Not = 0x66, - Or = 0x60, - Pop = 0x26, - Readonly = 0xFE1E, - Refanytype = 0xFF1D, - Refanyval = 0xC2, - Rem = 0x5D, - RemUn = 0x5E, - Ret = 0x2A, - Rethrow = 0xFF1A, - Shl = 0x62, - Shr = 0x63, - ShrUn = 0x64, - Sizeof = 0xFE1C, - Starg = 0xFE0B, - StargS = 0x10, - Stelem = 0xA4, - StelemI = 0x9B, - StelemI1 = 0x9C, - StelemI2 = 0x9D, - StelemI4 = 0x9E, - StelemI8 = 0x9F, - StelemR4 = 0xA0, - StelemR8 = 0xA1, - StelemRef = 0xA2, - Stfld = 0x7D, - StindI = 0xDF, - StindI1 = 0x52, - StintI2 = 0x53, - StindI4 = 0x54, - StindI8 = 0x55, - StindR4 = 0x56, - StintR8 = 0x57, - StindRef = 0x51, - Stloc = 0xFF0E, - Stloc0 = 0x0A, - Stloc1 = 0x0B, - Stloc2 = 0x0C, - Stloc3 = 0x0D, - StlocS = 0x13, - Stobj = 0x81, - Stsfld = 0x80, - Sub = 0x59, - SubOvf = 0xDA, - SubOvfUn = 0xDB, - Switch = 0x45, - Tailcall = 0xFF14, - Throw = 0x7A, - Unaligned = 0xFE12, - Unbox = 0x79, - UnboxAny = 0xA5, - Volatile = 0xFE13, - Xor = 0x61, - }; - }; // namespace DotNet -} // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Emit/Java/JavaEmitter.h b/src/Mamba/Code Analysis/Emit/Java/JavaEmitter.h deleted file mode 100644 index deb73d3..0000000 --- a/src/Mamba/Code Analysis/Emit/Java/JavaEmitter.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "BoundBinaryExpression.h" -#include "BoundBinaryOperator.h" -#include "BoundBinaryOperatorKind.h" -#include "Emitter.h" - -namespace Mamba -{ - class JavaEmitter final : public Emitter - { - public: - void EmitBinaryExpression(const BoundBinaryExpression& Expression) - { - if (Expression.Operator.Kind == BoundBinaryOperatorKind::Addition) - { - // ldc insn Expression.Left - // ldc insn Expression.Right - // add - } - } - }; -} // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Linking/LinkIdentifier.h b/src/Mamba/Code Analysis/Linking/LinkIdentifier.h deleted file mode 100644 index 18a5cce..0000000 --- a/src/Mamba/Code Analysis/Linking/LinkIdentifier.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include - -namespace Mamba -{ - enum class LinkIdentifier : std::uint8_t - { - Function, - Variable, - Type, - Instruction, - String - }; -} // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Linking/Serializer.cpp b/src/Mamba/Code Analysis/Linking/Serializer.cpp deleted file mode 100644 index 027742d..0000000 --- a/src/Mamba/Code Analysis/Linking/Serializer.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "Serializer.h" - -#include - -#include "fast_io.h" - -using namespace Mamba; - -void Serializer::Write(const std::span DataView) noexcept -{ -#if __cpp_lib_containers_ranges == 202202L - Data.append_range(DataView); -#else - const auto PreviousSize = Data.size(); - Data.resize(PreviousSize + DataView.size()); - std::memcpy(Data.data() + PreviousSize, DataView.data(), DataView.size()); -#endif -} - -void Serializer::Write(const StringView String) noexcept -{ - Write(String.size()); - - const auto First = reinterpret_cast(String.data()); - const auto Last = reinterpret_cast(String.data() + String.size()); - Write(std::span(First, Last)); -} diff --git a/src/Mamba/Code Analysis/Linking/Serializer.h b/src/Mamba/Code Analysis/Linking/Serializer.h deleted file mode 100644 index d4787bf..0000000 --- a/src/Mamba/Code Analysis/Linking/Serializer.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include "MambaCore.h" -#include -#include -#include -#include -#include - -namespace Mamba -{ - class Serializer final - { - public: - std::vector Data; - - void Write(const std::span DataView) noexcept; - - template - requires std::is_trivially_copyable_v && (!std::is_integral_v) - void Write(const T& Data) noexcept - { - using ByteArray = std::array; - const auto ValueRepresentation = std::bit_cast(Data); - Write(std::span(ValueRepresentation)); - } - - template - void Write(const T Data) noexcept - { - static_assert( - std::endian::native == std::endian::little || std::endian::native == std::endian::big, - "Unsupported endianness" - ); - static_assert(std::has_unique_object_representations_v, "T may not have padding bits"); - - using ByteArray = std::array; - auto ValueRepresentation = std::bit_cast(Data); - if constexpr (std::endian::native == std::endian::big) - { - // Dotnet linker reads integers as little-endian - std::ranges::reverse(ValueRepresentation); - } - - Write(ValueRepresentation); - } - - void Write(const StringView String) noexcept; - }; -} // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Symbol/FunctionSymbol.cpp b/src/Mamba/Code Analysis/Symbol/FunctionSymbol.cpp index 0f29825..83ee1cf 100644 --- a/src/Mamba/Code Analysis/Symbol/FunctionSymbol.cpp +++ b/src/Mamba/Code Analysis/Symbol/FunctionSymbol.cpp @@ -1,38 +1,22 @@ #include "FunctionSymbol.h" -#include "fast_io.h" +#include "TypeSymbol.h" -namespace Mamba +using namespace Mamba; + +FunctionSymbol::FunctionSymbol(StringView Name, std::vector&& Parameters, const TypeSymbol* Type, const BoundFunctionDeclaration* BoundDeclaration) noexcept : + Super(Name), Parameters(std::move(Parameters)), BoundDeclaration(BoundDeclaration), Type(Type) { - FunctionSymbol::FunctionSymbol( - const std::shared_ptr Name, - const std::span> Parameters, - const std::shared_ptr Type, - const std::shared_ptr BoundDeclaration - ) noexcept : - Super(Name), -#if __cpp_lib_containers_ranges == 202202L - Parameters(std::from_range, Parameters) -#else - Parameters(Parameters.begin(), Parameters.end()) -#endif - , - BoundDeclaration(BoundDeclaration), - Type(Type) - { - } +} - FunctionSymbol::FunctionSymbol( - const std::shared_ptr Name, - std::vector>&& Parameters, - const std::shared_ptr Type, - const std::shared_ptr BoundDeclaration - ) noexcept : - Super(Name), Parameters(std::move(Parameters)), BoundDeclaration(BoundDeclaration), Type(Type) +FunctionSymbol::~FunctionSymbol() noexcept +{ + if (!TypeSymbol::IsBuiltInType(Type)) { + delete Type; } +} - SymbolKind FunctionSymbol::Kind() const noexcept - { - return SymbolKind::Function; - } -} // namespace Mamba \ No newline at end of file +SymbolKind FunctionSymbol::Kind() const noexcept +{ + return SymbolKind::Function; +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Symbol/FunctionSymbol.h b/src/Mamba/Code Analysis/Symbol/FunctionSymbol.h index b1b7068..83a19f1 100644 --- a/src/Mamba/Code Analysis/Symbol/FunctionSymbol.h +++ b/src/Mamba/Code Analysis/Symbol/FunctionSymbol.h @@ -2,9 +2,8 @@ #include "BoundFunctionDeclaration.h" #include "MambaCore.h" +#include "ParameterSymbol.h" #include "Symbol.h" -#include -#include namespace Mamba { @@ -13,24 +12,13 @@ namespace Mamba public: using Super = Symbol; - [[nodiscard]] FunctionSymbol( - const std::shared_ptr Name, - const std::span> Parameters, - const std::shared_ptr Type, - const std::shared_ptr BoundDeclaration - ) noexcept; - - [[nodiscard]] FunctionSymbol( - const std::shared_ptr Name, - std::vector>&& Parameters, - const std::shared_ptr Type, - const std::shared_ptr BoundDeclaration - ) noexcept; - - std::vector> Parameters; - std::shared_ptr BoundDeclaration; - std::shared_ptr Type; + [[nodiscard]] FunctionSymbol(StringView Name, std::vector&& Parameters, const TypeSymbol* Type, const BoundFunctionDeclaration* BoundDeclaration) noexcept; + ~FunctionSymbol() noexcept override; SymbolKind Kind() const noexcept override; + + std::vector Parameters; + const BoundFunctionDeclaration* BoundDeclaration; + const TypeSymbol* Type; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Symbol/ParameterSymbol.cpp b/src/Mamba/Code Analysis/Symbol/ParameterSymbol.cpp index ddefaba..4cfeea8 100644 --- a/src/Mamba/Code Analysis/Symbol/ParameterSymbol.cpp +++ b/src/Mamba/Code Analysis/Symbol/ParameterSymbol.cpp @@ -2,19 +2,22 @@ #include "TypeSymbol.h" -namespace Mamba +using namespace Mamba; + +ParameterSymbol::ParameterSymbol(StringView Name, const TypeSymbol* Type, std::size_t Oridinal) noexcept : + Super(Name, false, Type, {}), Oridinal(Oridinal) { - ParameterSymbol::ParameterSymbol( - const std::shared_ptr Name, - const std::shared_ptr Type, - const std::size_t Oridinal - ) noexcept : - Super(Name, false, Type, nullptr), Oridinal(Oridinal) - { - } +} - SymbolKind ParameterSymbol::Kind() const noexcept +ParameterSymbol::~ParameterSymbol() noexcept +{ + if (!TypeSymbol::IsBuiltInType(Type)) { - return SymbolKind::Parameter; + delete Type; } -} // namespace Mamba \ No newline at end of file +} + +SymbolKind ParameterSymbol::Kind() const noexcept +{ + return SymbolKind::Parameter; +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Symbol/ParameterSymbol.h b/src/Mamba/Code Analysis/Symbol/ParameterSymbol.h index 394430a..dba7081 100644 --- a/src/Mamba/Code Analysis/Symbol/ParameterSymbol.h +++ b/src/Mamba/Code Analysis/Symbol/ParameterSymbol.h @@ -1,7 +1,5 @@ #pragma once -#include - #include "MambaCore.h" #include "VariableSymbol.h" @@ -12,14 +10,11 @@ namespace Mamba public: using Super = VariableSymbol; - [[nodiscard]] ParameterSymbol( - const std::shared_ptr Name, - const std::shared_ptr Type, - const std::size_t Oridinal - ) noexcept; - - const std::size_t Oridinal; + [[nodiscard]] ParameterSymbol(StringView Name, const TypeSymbol* Type, std::size_t Oridinal) noexcept; + ~ParameterSymbol() noexcept override; SymbolKind Kind() const noexcept override; + + std::size_t Oridinal; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Symbol/Symbol.cpp b/src/Mamba/Code Analysis/Symbol/Symbol.cpp index 38d866f..f41870a 100644 --- a/src/Mamba/Code Analysis/Symbol/Symbol.cpp +++ b/src/Mamba/Code Analysis/Symbol/Symbol.cpp @@ -1,27 +1,31 @@ #include "Symbol.h" -#include "SymbolKind.h" -namespace Mamba +using namespace Mamba; + +Symbol::Symbol(StringView Name) noexcept : + PrivateName(Name) {} + +StringView Symbol::Name() const noexcept { - Symbol::Symbol(const std::shared_ptr Name) noexcept : Name(Name) {} + return PrivateName; +} - bool Symbol::IsFunction() const noexcept - { - return Kind() == SymbolKind::Function; - } +bool Symbol::IsFunction() const noexcept +{ + return Kind() == SymbolKind::Function; +} - bool Symbol::IsVariable() const noexcept - { - return Kind() == SymbolKind::Variable; - } +bool Symbol::IsVariable() const noexcept +{ + return Kind() == SymbolKind::Variable; +} - bool Symbol::IsParameter() const noexcept - { - return Kind() == SymbolKind::Parameter; - } +bool Symbol::IsParameter() const noexcept +{ + return Kind() == SymbolKind::Parameter; +} - bool Symbol::IsType() const noexcept - { - return Kind() == SymbolKind::Type; - } -} // namespace Mamba \ No newline at end of file +bool Symbol::IsType() const noexcept +{ + return Kind() == SymbolKind::Type; +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Symbol/Symbol.h b/src/Mamba/Code Analysis/Symbol/Symbol.h index e275138..c2c9cbe 100644 --- a/src/Mamba/Code Analysis/Symbol/Symbol.h +++ b/src/Mamba/Code Analysis/Symbol/Symbol.h @@ -8,13 +8,14 @@ namespace Mamba { class Symbol { + StringView PrivateName; + protected: - [[nodiscard]] Symbol(const std::shared_ptr Name) noexcept; + [[nodiscard]] Symbol(StringView Name) noexcept; virtual ~Symbol() = default; public: - const std::shared_ptr Name; - + [[nodiscard]] StringView Name() const noexcept; [[nodiscard]] virtual SymbolKind Kind() const noexcept = 0; [[nodiscard]] bool IsFunction() const noexcept; [[nodiscard]] bool IsVariable() const noexcept; diff --git a/src/Mamba/Code Analysis/Symbol/TypeSymbol.cpp b/src/Mamba/Code Analysis/Symbol/TypeSymbol.cpp index 7a053aa..7cecf1b 100644 --- a/src/Mamba/Code Analysis/Symbol/TypeSymbol.cpp +++ b/src/Mamba/Code Analysis/Symbol/TypeSymbol.cpp @@ -2,21 +2,24 @@ using namespace Mamba; -// why qualified name is required here? -TypeSymbol::TypeSymbol(const std::shared_ptr Name) noexcept : Super(Name) {} - -Mamba::TypeSymbol::~TypeSymbol() noexcept {} +TypeSymbol::TypeSymbol(StringView Name) noexcept : + Super(Name) {} SymbolKind TypeSymbol::Kind() const noexcept { return SymbolKind::Type; } -const std::shared_ptr TypeSymbol::Int = - std::make_shared(std::make_shared(TEXT("int"))); -const std::shared_ptr TypeSymbol::Bool = - std::make_shared(std::make_shared(TEXT("bool"))); -const std::shared_ptr TypeSymbol::String = - std::make_shared(std::make_shared(TEXT("string"))); -const std::shared_ptr TypeSymbol::Void = - std::make_shared(std::make_shared(TEXT("void"))); \ No newline at end of file +bool TypeSymbol::IsBuiltInType(const TypeSymbol* Type) noexcept +{ + return Type == &TypeSymbol::Int || + Type == &TypeSymbol::Bool || + Type == &TypeSymbol::String || + Type == &TypeSymbol::Void; +} + +const TypeSymbol TypeSymbol::Int = TypeSymbol(TEXT("int")); +const TypeSymbol TypeSymbol::Bool = TypeSymbol(TEXT("bool")); +const TypeSymbol TypeSymbol::String = TypeSymbol(TEXT("string")); +const TypeSymbol TypeSymbol::Void = TypeSymbol(TEXT("void")); +const TypeSymbol TypeSymbol::Double = TypeSymbol(TEXT("double")); \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Symbol/TypeSymbol.h b/src/Mamba/Code Analysis/Symbol/TypeSymbol.h index a080f56..e828ddf 100644 --- a/src/Mamba/Code Analysis/Symbol/TypeSymbol.h +++ b/src/Mamba/Code Analysis/Symbol/TypeSymbol.h @@ -13,14 +13,17 @@ namespace Mamba public: using Super = Symbol; - [[nodiscard]] TypeSymbol(const std::shared_ptr Name) noexcept; - virtual ~TypeSymbol() noexcept; + [[nodiscard]] TypeSymbol(StringView Name) noexcept; + virtual ~TypeSymbol() noexcept = default; SymbolKind Kind() const noexcept override; - static const std::shared_ptr Int; - static const std::shared_ptr Bool; - static const std::shared_ptr String; - static const std::shared_ptr Void; + static const TypeSymbol Int; + static const TypeSymbol Bool; + static const TypeSymbol String; + static const TypeSymbol Void; + static const TypeSymbol Double; + + static bool IsBuiltInType(const TypeSymbol* Type) noexcept; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Symbol/VariableSymbol.cpp b/src/Mamba/Code Analysis/Symbol/VariableSymbol.cpp index ba06bda..5501359 100644 --- a/src/Mamba/Code Analysis/Symbol/VariableSymbol.cpp +++ b/src/Mamba/Code Analysis/Symbol/VariableSymbol.cpp @@ -1,22 +1,21 @@ #include "VariableSymbol.h" -#include "TypeSymbol.h" +using namespace Mamba; -namespace Mamba +VariableSymbol::VariableSymbol(StringView Name, bool IsConstant, const TypeSymbol* Type, struct Constant Constant) noexcept : + Super(Name), IsConstant(IsConstant), Type(Type), Constant(Constant) { - VariableSymbol::VariableSymbol( - const std::shared_ptr Name, - const bool IsConstant, - const std::shared_ptr Type, - const NullableSharedPtr Constant - ) noexcept : - Super(Name), IsConstant(IsConstant), Type(Type), Constant(Constant) - { - } +} - SymbolKind VariableSymbol::Kind() const noexcept +VariableSymbol::~VariableSymbol() noexcept +{ + if (!TypeSymbol::IsBuiltInType(Type)) { - return SymbolKind::Variable; + delete Type; } +} -} // namespace Mamba \ No newline at end of file +SymbolKind VariableSymbol::Kind() const noexcept +{ + return SymbolKind::Variable; +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Symbol/VariableSymbol.h b/src/Mamba/Code Analysis/Symbol/VariableSymbol.h index d037a07..0f61d23 100644 --- a/src/Mamba/Code Analysis/Symbol/VariableSymbol.h +++ b/src/Mamba/Code Analysis/Symbol/VariableSymbol.h @@ -1,10 +1,10 @@ #pragma once -#include - +#include "Constant.h" #include "MambaCore.h" #include "Symbol.h" #include "SymbolKind.h" +#include "TypeSymbol.h" namespace Mamba { @@ -13,17 +13,13 @@ namespace Mamba public: using Super = Symbol; - [[nodiscard]] VariableSymbol( - const std::shared_ptr Name, - const bool IsConstant, - const std::shared_ptr Type, - const NullableSharedPtr Constant - ) noexcept; + [[nodiscard]] VariableSymbol(StringView Name, bool IsConstant, const TypeSymbol* Type, struct Constant Constant) noexcept; + ~VariableSymbol() noexcept override; SymbolKind Kind() const noexcept override; - const bool IsConstant; - const std::shared_ptr Type; - const NullableSharedPtr Constant; + bool IsConstant; + const TypeSymbol* Type; + struct Constant Constant; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/AssignmentExpressionSyntax.cpp b/src/Mamba/Code Analysis/Syntax/AssignmentExpressionSyntax.cpp index a69820b..2eb8c6e 100644 --- a/src/Mamba/Code Analysis/Syntax/AssignmentExpressionSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/AssignmentExpressionSyntax.cpp @@ -1,24 +1,43 @@ #include "AssignmentExpressionSyntax.h" -namespace Mamba +using namespace Mamba; + +AssignmentExpressionSyntax::AssignmentExpressionSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* IdentifierToken, + const SyntaxToken* AssignmentToken, + const ExpressionSyntax* Expression +) noexcept : + Super(SyntaxTree), IdentifierToken(IdentifierToken), AssignmentToken(AssignmentToken), Expression(Expression) { - AssignmentExpressionSyntax::AssignmentExpressionSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr IdentifierToken, - const std::shared_ptr AssignmentToken, - const std::shared_ptr Expression - ) noexcept : - Super(SyntaxTree), IdentifierToken(IdentifierToken), AssignmentToken(AssignmentToken), Expression(Expression) - { - } +} - std::vector> AssignmentExpressionSyntax::Children() const noexcept - { - return { IdentifierToken, AssignmentToken, Expression }; - } +AssignmentExpressionSyntax::~AssignmentExpressionSyntax() noexcept +{ + delete Expression; +} - SyntaxKind AssignmentExpressionSyntax::Kind() const noexcept +SyntaxKind AssignmentExpressionSyntax::Kind() const noexcept +{ + return SyntaxKind::AssignmentExpression; +} + +std::size_t AssignmentExpressionSyntax::ChildrenCount() const noexcept +{ + return 3; +} + +const SyntaxNode* AssignmentExpressionSyntax::ChildAt(std::size_t Index) const noexcept +{ + switch (Index) { - return SyntaxKind::AssignmentExpression; + case 0: + return IdentifierToken; + case 1: + return AssignmentToken; + case 2: + return Expression; + default: + ReportChildrenAccessOutOfBounds(Index); } -} // namespace Mamba \ No newline at end of file +} diff --git a/src/Mamba/Code Analysis/Syntax/AssignmentExpressionSyntax.h b/src/Mamba/Code Analysis/Syntax/AssignmentExpressionSyntax.h index 4de09da..f5937f5 100644 --- a/src/Mamba/Code Analysis/Syntax/AssignmentExpressionSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/AssignmentExpressionSyntax.h @@ -3,8 +3,6 @@ #include "ExpressionSyntax.h" #include "SyntaxKind.h" #include "SyntaxToken.h" -#include -#include namespace Mamba { @@ -14,17 +12,22 @@ namespace Mamba using Super = ExpressionSyntax; [[nodiscard]] AssignmentExpressionSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr IdentifierToken, - const std::shared_ptr AssignmentToken, - const std::shared_ptr Expression + const class SyntaxTree* SyntaxTree, + const SyntaxToken* IdentifierToken, + const SyntaxToken* AssignmentToken, + const ExpressionSyntax* Expression ) noexcept; - std::vector> Children() const noexcept override; + ~AssignmentExpressionSyntax() noexcept override; + SyntaxKind Kind() const noexcept override; - const std::shared_ptr IdentifierToken; - const std::shared_ptr AssignmentToken; - const std::shared_ptr Expression; + const SyntaxToken* IdentifierToken; + const SyntaxToken* AssignmentToken; + const ExpressionSyntax* Expression; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/BinaryExpressionSyntax.cpp b/src/Mamba/Code Analysis/Syntax/BinaryExpressionSyntax.cpp index b87e33e..0eee0ca 100644 --- a/src/Mamba/Code Analysis/Syntax/BinaryExpressionSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/BinaryExpressionSyntax.cpp @@ -1,24 +1,44 @@ #include "BinaryExpressionSyntax.h" -namespace Mamba +using namespace Mamba; + +BinaryExpressionSyntax::BinaryExpressionSyntax( + const class SyntaxTree* SyntaxTree, + const ExpressionSyntax* Left, + const SyntaxToken* OperatorToken, + const ExpressionSyntax* Right +) noexcept : + Super(SyntaxTree), Left(Left), OperatorToken(OperatorToken), Right(Right) { - BinaryExpressionSyntax::BinaryExpressionSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr Left, - const std::shared_ptr OperatorToken, - const std::shared_ptr Right - ) noexcept : - Super(SyntaxTree), Left(Left), OperatorToken(OperatorToken), Right(Right) - { - } +} - SyntaxKind BinaryExpressionSyntax::Kind() const noexcept - { - return SyntaxKind::BinaryExpression; - } +BinaryExpressionSyntax::~BinaryExpressionSyntax() noexcept +{ + delete Left; + delete Right; +} - std::vector> BinaryExpressionSyntax::Children() const noexcept +SyntaxKind BinaryExpressionSyntax::Kind() const noexcept +{ + return SyntaxKind::BinaryExpression; +} + +std::size_t BinaryExpressionSyntax::ChildrenCount() const noexcept +{ + return 3; +} + +const SyntaxNode* BinaryExpressionSyntax::ChildAt(std::size_t Index) const noexcept +{ + switch (Index) { - return { Left, OperatorToken, Right }; + case 0: + return Left; + case 1: + return OperatorToken; + case 2: + return Right; + default: + ReportChildrenAccessOutOfBounds(Index); } -} // namespace Mamba \ No newline at end of file +} diff --git a/src/Mamba/Code Analysis/Syntax/BinaryExpressionSyntax.h b/src/Mamba/Code Analysis/Syntax/BinaryExpressionSyntax.h index 95e4a5e..77f26a0 100644 --- a/src/Mamba/Code Analysis/Syntax/BinaryExpressionSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/BinaryExpressionSyntax.h @@ -3,7 +3,6 @@ #include "ExpressionSyntax.h" #include "SyntaxKind.h" #include "SyntaxToken.h" -#include namespace Mamba { @@ -12,16 +11,23 @@ namespace Mamba public: using Super = ExpressionSyntax; - [[nodiscard]] BinaryExpressionSyntax(const std::shared_ptr SyntaxTree, - const std::shared_ptr Left, - const std::shared_ptr OperatorToken, - const std::shared_ptr Right) noexcept; + [[nodiscard]] BinaryExpressionSyntax( + const class SyntaxTree* SyntaxTree, + const ExpressionSyntax* Left, + const SyntaxToken* OperatorToken, + const ExpressionSyntax* Right + ) noexcept; + + ~BinaryExpressionSyntax() noexcept override; SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - std::shared_ptr Left; - std::shared_ptr OperatorToken; - std::shared_ptr Right; + const ExpressionSyntax* Left; + const SyntaxToken* OperatorToken; + const ExpressionSyntax* Right; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba diff --git a/src/Mamba/Code Analysis/Syntax/BlockStatementSyntax.cpp b/src/Mamba/Code Analysis/Syntax/BlockStatementSyntax.cpp index 6de956a..95dfe00 100644 --- a/src/Mamba/Code Analysis/Syntax/BlockStatementSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/BlockStatementSyntax.cpp @@ -1,54 +1,52 @@ #include "BlockStatementSyntax.h" -#include "SyntaxNode.h" -#include "SyntaxToken.h" - -#include +using namespace Mamba; + +BlockStatementSyntax::BlockStatementSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* OpenBraceToken, + std::vector&& Statements, + const SyntaxToken* CloseBraceToken +) noexcept : + Super(SyntaxTree), + OpenBraceToken(OpenBraceToken), + Statements(std::move(Statements)), + CloseBraceToken(CloseBraceToken) +{ +} -namespace Mamba +BlockStatementSyntax::~BlockStatementSyntax() noexcept { - BlockStatementSyntax::BlockStatementSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr OpenBraceToken, - const std::vector>& Statements, - const std::shared_ptr CloseBraceToken) noexcept : - Super(SyntaxTree), OpenBraceToken(OpenBraceToken), Statements(Statements), CloseBraceToken(CloseBraceToken) + for (auto&& Statement : Statements) { + delete Statement; } +} + +SyntaxKind BlockStatementSyntax::Kind() const noexcept +{ + return SyntaxKind::BlockStatement; +} + +std::size_t BlockStatementSyntax::ChildrenCount() const noexcept +{ + return Statements.size() + 2; +} - BlockStatementSyntax::BlockStatementSyntax(const std::shared_ptr SyntaxTree, - const std::shared_ptr OpenBraceToken, - std::vector>&& Statements, - const std::shared_ptr CloseBraceToken) noexcept - : - Super(SyntaxTree), - OpenBraceToken(OpenBraceToken), - Statements(std::move(Statements)), - CloseBraceToken(CloseBraceToken) +const SyntaxNode* BlockStatementSyntax::ChildAt(std::size_t Index) const noexcept +{ + if (Index == 0) { + return OpenBraceToken; } - - SyntaxKind BlockStatementSyntax::Kind() const noexcept + else if (Index < Statements.size() + 1) { - return SyntaxKind::BlockStatement; + return Statements[Index - 1]; } - - std::vector> BlockStatementSyntax::Children() const noexcept + else if (Index == Statements.size() + 1) { - auto Result = std::vector>(); - Result.reserve(Statements.size() + 2); - - Result.emplace_back(OpenBraceToken); -#if __cpp_lib_containers_ranges == 202202L - Result.append_range(Statements); -#else - for (auto&& Statement : Statements) - { - Result.emplace_back(std::forward(Statement)); - } -#endif - Result.emplace_back(CloseBraceToken); - - return Result; + return CloseBraceToken; } -} // namespace Mamba \ No newline at end of file + + ReportChildrenAccessOutOfBounds(Index); +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/BlockStatementSyntax.h b/src/Mamba/Code Analysis/Syntax/BlockStatementSyntax.h index b5f000e..a22ea77 100644 --- a/src/Mamba/Code Analysis/Syntax/BlockStatementSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/BlockStatementSyntax.h @@ -2,8 +2,8 @@ #include "StatementSyntax.h" #include "SyntaxKind.h" +#include "SyntaxToken.h" -#include #include namespace Mamba @@ -13,21 +13,23 @@ namespace Mamba public: using Super = StatementSyntax; - [[nodiscard]] BlockStatementSyntax(const std::shared_ptr SyntaxTree, - const std::shared_ptr OpenBraceToken, - const std::vector>& Statements, - const std::shared_ptr CloseBraceToken) noexcept; + [[nodiscard]] BlockStatementSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* OpenBraceToken, + std::vector&& Statements, + const SyntaxToken* CloseBraceToken + ) noexcept; - [[nodiscard]] BlockStatementSyntax(const std::shared_ptr SyntaxTree, - const std::shared_ptr OpenBraceToken, - std::vector>&& Statements, - const std::shared_ptr CloseBraceToken) noexcept; + ~BlockStatementSyntax() noexcept override; SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::shared_ptr OpenBraceToken; - const std::vector> Statements; - const std::shared_ptr CloseBraceToken; + const SyntaxToken* OpenBraceToken; + std::vector Statements; + const SyntaxToken* CloseBraceToken; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/BreakStatementSyntax.cpp b/src/Mamba/Code Analysis/Syntax/BreakStatementSyntax.cpp index 6ae3f0b..0b70ae7 100644 --- a/src/Mamba/Code Analysis/Syntax/BreakStatementSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/BreakStatementSyntax.cpp @@ -2,21 +2,29 @@ #include "SyntaxToken.h" -namespace Mamba +using namespace Mamba; + +BreakStatementSyntax::BreakStatementSyntax(const class SyntaxTree* SyntaxTree, const SyntaxToken* Keyword) noexcept : + Super(SyntaxTree), Keyword(Keyword) { - BreakStatementSyntax::BreakStatementSyntax(const std::shared_ptr SyntaxTree, - const std::shared_ptr Keyword) noexcept : - Super(SyntaxTree), Keyword(Keyword) - { - } +} - SyntaxKind BreakStatementSyntax::Kind() const noexcept - { - return SyntaxKind::BreakStatement; - } +SyntaxKind BreakStatementSyntax::Kind() const noexcept +{ + return SyntaxKind::BreakStatement; +} + +std::size_t BreakStatementSyntax::ChildrenCount() const noexcept +{ + return 1; +} - std::vector> BreakStatementSyntax::Children() const noexcept +const SyntaxNode* BreakStatementSyntax::ChildAt(std::size_t Index) const noexcept +{ + if (Index != 0) { - return { Keyword }; + ReportChildrenAccessOutOfBounds(Index); } -} // namespace Mamba \ No newline at end of file + + return Keyword; +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/BreakStatementSyntax.h b/src/Mamba/Code Analysis/Syntax/BreakStatementSyntax.h index 335edb5..0b577c2 100644 --- a/src/Mamba/Code Analysis/Syntax/BreakStatementSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/BreakStatementSyntax.h @@ -1,7 +1,7 @@ #pragma once #include "StatementSyntax.h" -#include +#include "SyntaxToken.h" namespace Mamba { @@ -10,12 +10,14 @@ namespace Mamba public: using Super = StatementSyntax; - [[nodiscard]] BreakStatementSyntax(const std::shared_ptr SyntaxTree, - const std::shared_ptr Keyword) noexcept; + [[nodiscard]] BreakStatementSyntax(const class SyntaxTree* SyntaxTree, const SyntaxToken* Keyword) noexcept; SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::shared_ptr Keyword; + const SyntaxToken* Keyword; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/CallExpressionSyntax.cpp b/src/Mamba/Code Analysis/Syntax/CallExpressionSyntax.cpp index 8a39a3f..03ea455 100644 --- a/src/Mamba/Code Analysis/Syntax/CallExpressionSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/CallExpressionSyntax.cpp @@ -1,44 +1,58 @@ #include "CallExpressionSyntax.h" -namespace Mamba +using namespace Mamba; + +CallExpressionSyntax::CallExpressionSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* Identifier, + const SyntaxToken* OpenParenthesisToken, + SeperatedSyntaxList Arguments, + const SyntaxToken* CloseParenthesisToken +) noexcept : + Super(SyntaxTree), + Identifier(Identifier), + OpenParenthesisToken(OpenParenthesisToken), + Arguments(Arguments), + CloseParenthesisToken(CloseParenthesisToken) { - CallExpressionSyntax::CallExpressionSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr Identifier, - const std::shared_ptr OpenParenthesisToken, - const std::shared_ptr>> Arguments, - const std::shared_ptr CloseParenthesisToken) noexcept : - Super(SyntaxTree), - Identifier(Identifier), - OpenParenthesisToken(OpenParenthesisToken), - Arguments(Arguments), - CloseParenthesisToken(CloseParenthesisToken) - { - } +} - SyntaxKind CallExpressionSyntax::Kind() const noexcept +CallExpressionSyntax::~CallExpressionSyntax() noexcept +{ + for (auto Argument : Arguments.Nodes()) { - return SyntaxKind::CallExpression; + delete Argument; } +} - std::vector> CallExpressionSyntax::Children() const noexcept - { - auto Result = std::vector>(); +SyntaxKind CallExpressionSyntax::Kind() const noexcept +{ + return SyntaxKind::CallExpression; +} - // Arguments->Count() returns nodes count, so multiply by 2 to count with separators - Result.reserve(2 + Arguments->Count() * 2); - Result.emplace_back(Identifier); - Result.emplace_back(OpenParenthesisToken); -#if __cpp_lib_containers_ranges == 202202L - Result.append_range(Arguments->WithSeperators()); -#else - for (auto&& Argument : Arguments->WithSeperators()) - { - Result.emplace_back(std::forward(Argument)); - } -#endif - Result.emplace_back(CloseParenthesisToken); +std::size_t CallExpressionSyntax::ChildrenCount() const noexcept +{ + return 2 + Arguments.size(); +} - return Result; +const SyntaxNode* CallExpressionSyntax::ChildAt(std::size_t Index) const noexcept +{ + if (Index == 0) + { + return Identifier; + } + else if (Index == 1) + { + return OpenParenthesisToken; + } + else if (Index < Arguments.size() + 2) + { + return Arguments[Index - 2]; + } + else if (Index == Arguments.size() + 2) + { + return CloseParenthesisToken; } -} // namespace Mamba \ No newline at end of file + + ReportChildrenAccessOutOfBounds(Index); +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/CallExpressionSyntax.h b/src/Mamba/Code Analysis/Syntax/CallExpressionSyntax.h index 729032c..96edb7b 100644 --- a/src/Mamba/Code Analysis/Syntax/CallExpressionSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/CallExpressionSyntax.h @@ -4,7 +4,6 @@ #include "SeperatedSyntaxList.h" #include "SyntaxNode.h" #include "SyntaxToken.h" -#include namespace Mamba { @@ -14,18 +13,24 @@ namespace Mamba using Super = ExpressionSyntax; [[nodiscard]] CallExpressionSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr Identifier, - const std::shared_ptr OpenParenthesisToken, - const std::shared_ptr>> Arguments, - const std::shared_ptr CloseParenthesisToken) noexcept; + const class SyntaxTree* SyntaxTree, + const SyntaxToken* Identifier, + const SyntaxToken* OpenParenthesisToken, + SeperatedSyntaxList Arguments, + const SyntaxToken* CloseParenthesisToken + ) noexcept; + + ~CallExpressionSyntax() noexcept override; SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::shared_ptr Identifier; - const std::shared_ptr OpenParenthesisToken; - const std::shared_ptr>> Arguments; - const std::shared_ptr CloseParenthesisToken; + const SyntaxToken* Identifier; + const SyntaxToken* OpenParenthesisToken; + SeperatedSyntaxList Arguments; + const SyntaxToken* CloseParenthesisToken; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/CompilationUnitSyntax.cpp b/src/Mamba/Code Analysis/Syntax/CompilationUnitSyntax.cpp index c3da19f..02de407 100644 --- a/src/Mamba/Code Analysis/Syntax/CompilationUnitSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/CompilationUnitSyntax.cpp @@ -1,44 +1,40 @@ #include "CompilationUnitSyntax.h" -#include "MemberSyntax.h" -#include "SyntaxNode.h" -#include "SyntaxToken.h" -namespace Mamba +using namespace Mamba; + +CompilationUnitSyntax::CompilationUnitSyntax(const SyntaxTree* SyntaxTree, std::vector&& Members, const SyntaxToken* EndOfFileToken) noexcept : + Super(SyntaxTree), Members(std::move(Members)), EndOfFileToken(EndOfFileToken) { +} - CompilationUnitSyntax::CompilationUnitSyntax(const std::shared_ptr SyntaxTree, - const std::vector>& Members, - std::shared_ptr EndOfFileToken) noexcept : - Super(SyntaxTree), Members(Members), EndOfFileToken(EndOfFileToken) +CompilationUnitSyntax::~CompilationUnitSyntax() noexcept +{ + for (auto&& Member : Members) { + delete Member; } +} - CompilationUnitSyntax::CompilationUnitSyntax(const std::shared_ptr SyntaxTree, - std::vector>&& Members, - std::shared_ptr EndOfFileToken) noexcept : - Super(SyntaxTree), Members(std::move(Members)), EndOfFileToken(EndOfFileToken) - { - } +SyntaxKind CompilationUnitSyntax::Kind() const noexcept +{ + return SyntaxKind::CompilationUnit; +} - SyntaxKind CompilationUnitSyntax::Kind() const noexcept +std::size_t CompilationUnitSyntax::ChildrenCount() const noexcept +{ + return Members.size() + 1; +} + +const SyntaxNode* CompilationUnitSyntax::ChildAt(std::size_t Index) const noexcept +{ + if (Index < Members.size()) { - return SyntaxKind::CompilationUnit; + return Members[Index]; } - - std::vector> CompilationUnitSyntax::Children() const noexcept + else if (Index == Members.size()) { - auto Children = std::vector>(); - Children.reserve(Members.size() + 1); -#if __cpp_lib_containers_ranges == 202202L - Children.append_range(Members); -#else - for (auto&& Member : Members) - { - Children.emplace_back(std::forward(Member)); - } -#endif - Children.emplace_back(EndOfFileToken); - return Children; + return EndOfFileToken; } -} // namespace Mamba + ReportChildrenAccessOutOfBounds(Index); +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/CompilationUnitSyntax.h b/src/Mamba/Code Analysis/Syntax/CompilationUnitSyntax.h index a33ce58..3b2490f 100644 --- a/src/Mamba/Code Analysis/Syntax/CompilationUnitSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/CompilationUnitSyntax.h @@ -1,8 +1,8 @@ #pragma once +#include "MemberSyntax.h" #include "SyntaxNode.h" - -#include +#include "SyntaxToken.h" namespace Mamba { @@ -12,19 +12,22 @@ namespace Mamba public: using Super = SyntaxNode; - [[nodiscard]] CompilationUnitSyntax(const std::shared_ptr SyntaxTree, - const std::vector>& Members, - std::shared_ptr EndOfFileToken) noexcept; + [[nodiscard]] CompilationUnitSyntax( + const class SyntaxTree* SyntaxTree, + std::vector&& Members, + const SyntaxToken* EndOfFileToken + ) noexcept; - [[nodiscard]] CompilationUnitSyntax(const std::shared_ptr SyntaxTree, - std::vector>&& Members, - std::shared_ptr EndOfFileToken) noexcept; + ~CompilationUnitSyntax() noexcept override; SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::vector> Members; - std::shared_ptr EndOfFileToken; + std::vector Members; + const SyntaxToken* EndOfFileToken; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/Constant.h b/src/Mamba/Code Analysis/Syntax/Constant.h new file mode 100644 index 0000000..dd68052 --- /dev/null +++ b/src/Mamba/Code Analysis/Syntax/Constant.h @@ -0,0 +1,367 @@ +#pragma once + +#include "MambaCore.h" +#include +#include + +namespace Mamba +{ + struct ConstantType + { + using String = StringView; + using Char = char; + + using Boolean = bool; + + using Float = float; + using Double = double; + + using Byte = std::byte; + using Short = std::int16_t; + using Int = std::int32_t; + using Long = std::int64_t; + + using UByte = std::uint8_t; + using UShort = std::uint16_t; + using UInt = std::uint32_t; + using ULong = std::uint64_t; + + using Empty = std::monostate; + }; + + struct Constant + { + using ValueType = std::variant; + + [[nodiscard]] constexpr Constant() noexcept = default; + + template + requires std::constructible_from + [[nodiscard]] constexpr Constant(T Value) noexcept : + Value(Value){}; + + template + [[nodiscard]] constexpr T Get() const noexcept + { + return std::get(Value); + } + + [[nodiscard]] constexpr bool IsValid() const noexcept + { + return !Value.valueless_by_exception(); + } + + [[nodiscard]] constexpr Constant operator-() noexcept + { + return std::visit( + [](T Value) -> Constant { + if constexpr (requires { -Value; }) + { + return -Value; + } + else + { + return {}; + } + }, + Value + ); + } + + [[nodiscard]] constexpr Constant operator!() noexcept + { + return std::visit( + [](T Value) -> Constant { + if constexpr (requires { !Value; }) + { + return !Value; + } + else + { + return {}; + } + }, + Value + ); + } + + [[nodiscard]] constexpr Constant operator~() noexcept + { + return std::visit( + [](T Value) -> Constant { + if constexpr (requires { ~Value; }) + { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wbool-operation" + return ~Value; +#pragma clang diagnostic pop + } + else + { + return {}; + } + }, + Value + ); + } + + [[nodiscard]] constexpr Constant operator+(Constant Other) const noexcept + { + return std::visit( + [](auto Left, auto Right) -> Constant { + if constexpr (requires { Left + Right; }) + { + return Left + Right; + } + else + { + return {}; + } + }, + Value, + Other.Value + ); + } + + [[nodiscard]] constexpr Constant operator-(Constant Other) const noexcept + { + return std::visit( + [](auto Left, auto Right) -> Constant { + if constexpr (requires { Left - Right; }) + { + return Left - Right; + } + else + { + return {}; + } + }, + Value, + Other.Value + ); + } + + [[nodiscard]] constexpr Constant operator*(Constant Other) const noexcept + { + return std::visit( + [](auto Left, auto Right) -> Constant { + if constexpr (requires { Left* Right; }) + { + return Left * Right; + } + else + { + return {}; + } + }, + Value, + Other.Value + ); + } + + [[nodiscard]] constexpr Constant operator/(Constant Other) const noexcept + { + return std::visit( + [](auto Left, auto Right) -> Constant { + if constexpr (requires { Left + Right; }) + { + return Left + Right; + } + else + { + return {}; + } + }, + Value, + Other.Value + ); + } + + [[nodiscard]] constexpr Constant operator&&(Constant Other) const noexcept + { + return std::visit( + [](auto Left, auto Right) -> Constant { + if constexpr (requires { Left&& Right; }) + { + return Left && Right; + } + else + { + return {}; + } + }, + Value, + Other.Value + ); + } + + [[nodiscard]] constexpr Constant operator||(Constant Other) const noexcept + { + return std::visit( + [](auto Left, auto Right) -> Constant { + if constexpr (requires { Left || Right; }) + { + return Left || Right; + } + else + { + return {}; + } + }, + Value, + Other.Value + ); + } + + [[nodiscard]] constexpr Constant operator&(Constant Other) const noexcept + { + return std::visit( + [](auto Left, auto Right) -> Constant { + if constexpr (requires { Left & Right; }) + { + return Left & Right; + } + else + { + return {}; + } + }, + Value, + Other.Value + ); + } + + [[nodiscard]] constexpr Constant operator|(Constant Other) const noexcept + { + return std::visit( + [](auto Left, auto Right) -> Constant { + if constexpr (requires { Left | Right; }) + { + return Left | Right; + } + else + { + return {}; + } + }, + Value, + Other.Value + ); + } + + [[nodiscard]] constexpr Constant operator^(Constant Other) const noexcept + { + return std::visit( + [](auto Left, auto Right) -> Constant { + if constexpr (requires { Left ^ Right; }) + { + return Left ^ Right; + } + else + { + return {}; + } + }, + Value, + Other.Value + ); + } + + [[nodiscard]] constexpr Constant operator==(Constant Other) const noexcept + { + return Value == Other.Value; + } + + [[nodiscard]] constexpr Constant operator!=(Constant Other) const noexcept + { + return Value != Other.Value; + } + + [[nodiscard]] constexpr Constant operator<(Constant Other) const noexcept + { + return std::visit( + [](auto Left, auto Right) -> Constant { + if constexpr (requires { Left < Right; }) + { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wsign-compare" + return Left < Right; +#pragma clang diagnostic pop + } + else + { + return {}; + } + }, + Value, + Other.Value + ); + } + + [[nodiscard]] constexpr Constant operator<=(Constant Other) const noexcept + { + return std::visit( + [](auto Left, auto Right) -> Constant { + if constexpr (requires { Left <= Right; }) + { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wsign-compare" + return Left < Right; +#pragma clang diagnostic pop + } + else + { + return {}; + } + }, + Value, + Other.Value + ); + } + + [[nodiscard]] constexpr Constant operator>(Constant Other) const noexcept + { + return std::visit( + [](auto Left, auto Right) -> Constant { + if constexpr (requires { Left > Right; }) + { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wsign-compare" + return Left > Right; +#pragma clang diagnostic pop + } + else + { + return {}; + } + }, + Value, + Other.Value + ); + } + + [[nodiscard]] constexpr Constant operator>=(Constant Other) const noexcept + { + return std::visit( + [](auto Left, auto Right) -> Constant { + if constexpr (requires { Left >= Right; }) + { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wsign-compare" + return Left > Right; +#pragma clang diagnostic pop + } + else + { + return {}; + } + }, + Value, + Other.Value + ); + } + + private: + ValueType Value; + }; +} // namespace Mamba diff --git a/src/Mamba/Code Analysis/Syntax/ContinueStatementSyntax.cpp b/src/Mamba/Code Analysis/Syntax/ContinueStatementSyntax.cpp index 75af896..00dd825 100644 --- a/src/Mamba/Code Analysis/Syntax/ContinueStatementSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/ContinueStatementSyntax.cpp @@ -2,22 +2,29 @@ #include "SyntaxToken.h" -namespace Mamba +using namespace Mamba; + +ContinueStatementSyntax::ContinueStatementSyntax(const class SyntaxTree* SyntaxTree, const SyntaxToken* Keyword) noexcept : + Super(SyntaxTree), Keyword(Keyword) { - ContinueStatementSyntax::ContinueStatementSyntax(const std::shared_ptr SyntaxTree, - const std::shared_ptr Keyword) noexcept : - Super(SyntaxTree), Keyword(Keyword) - { - } +} - SyntaxKind ContinueStatementSyntax::Kind() const noexcept - { - return SyntaxKind::ContinueStatement; - } +SyntaxKind ContinueStatementSyntax::Kind() const noexcept +{ + return SyntaxKind::ContinueStatement; +} + +std::size_t ContinueStatementSyntax::ChildrenCount() const noexcept +{ + return 1; +} - std::vector> ContinueStatementSyntax::Children() const noexcept +const SyntaxNode* ContinueStatementSyntax::ChildAt(std::size_t Index) const noexcept +{ + if (Index != 0) { - return { Keyword }; + ReportChildrenAccessOutOfBounds(Index); } -} // namespace Mamba \ No newline at end of file + return Keyword; +} diff --git a/src/Mamba/Code Analysis/Syntax/ContinueStatementSyntax.h b/src/Mamba/Code Analysis/Syntax/ContinueStatementSyntax.h index 62fdd87..3246309 100644 --- a/src/Mamba/Code Analysis/Syntax/ContinueStatementSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/ContinueStatementSyntax.h @@ -1,8 +1,7 @@ #pragma once #include "StatementSyntax.h" - -#include +#include "SyntaxToken.h" namespace Mamba { @@ -11,12 +10,14 @@ namespace Mamba public: using Super = StatementSyntax; - [[nodiscard]] ContinueStatementSyntax(const std::shared_ptr SyntaxTree, - const std::shared_ptr Keyword) noexcept; + [[nodiscard]] ContinueStatementSyntax(const class SyntaxTree* SyntaxTree, const SyntaxToken* Keyword) noexcept; SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::shared_ptr Keyword; + const SyntaxToken* Keyword; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/DoWhileStatementSyntax.cpp b/src/Mamba/Code Analysis/Syntax/DoWhileStatementSyntax.cpp index 7263bfd..4e615e9 100644 --- a/src/Mamba/Code Analysis/Syntax/DoWhileStatementSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/DoWhileStatementSyntax.cpp @@ -1,28 +1,47 @@ #include "DoWhileStatementSyntax.h" -#include "SyntaxToken.h" +using namespace Mamba; -namespace Mamba +DoWhileStatementSyntax::DoWhileStatementSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* DoKeyword, + const StatementSyntax* Body, + const SyntaxToken* WhileKeyword, + const ExpressionSyntax* Condition +) noexcept : + Super(SyntaxTree), DoKeyword(DoKeyword), Body(Body), WhileKeyword(WhileKeyword), Condition(Condition) { - DoWhileStatementSyntax::DoWhileStatementSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr DoKeyword, - const std::shared_ptr Body, - const std::shared_ptr WhileKeyword, - const std::shared_ptr Condition - ) noexcept : - Super(SyntaxTree), DoKeyword(DoKeyword), Body(Body), WhileKeyword(WhileKeyword), Condition(Condition) - { - } +} - SyntaxKind DoWhileStatementSyntax::Kind() const noexcept - { - return SyntaxKind::DoWhileStatement; - } +DoWhileStatementSyntax::~DoWhileStatementSyntax() noexcept +{ + delete Body; + delete Condition; +} - std::vector> DoWhileStatementSyntax::Children() const noexcept +SyntaxKind DoWhileStatementSyntax::Kind() const noexcept +{ + return SyntaxKind::DoWhileStatement; +} + +std::size_t DoWhileStatementSyntax::ChildrenCount() const noexcept +{ + return 4; +} + +const SyntaxNode* Mamba::DoWhileStatementSyntax::ChildAt(std::size_t Index) const noexcept +{ + switch (Index) { - return { DoKeyword, Body, WhileKeyword, Condition }; + case 0: + return DoKeyword; + case 1: + return Body; + case 2: + return WhileKeyword; + case 3: + return Condition; + default: + ReportChildrenAccessOutOfBounds(Index); } - -} // namespace Mamba \ No newline at end of file +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/DoWhileStatementSyntax.h b/src/Mamba/Code Analysis/Syntax/DoWhileStatementSyntax.h index faefc41..71d47cc 100644 --- a/src/Mamba/Code Analysis/Syntax/DoWhileStatementSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/DoWhileStatementSyntax.h @@ -3,8 +3,7 @@ #include "ExpressionSyntax.h" #include "StatementSyntax.h" #include "SyntaxKind.h" - -#include +#include "SyntaxToken.h" namespace Mamba { @@ -13,18 +12,25 @@ namespace Mamba public: using Super = StatementSyntax; - [[nodiscard]] DoWhileStatementSyntax(const std::shared_ptr SyntaxTree, - const std::shared_ptr DoKeyword, - const std::shared_ptr Body, - const std::shared_ptr WhileKeyword, - const std::shared_ptr Condition) noexcept; + [[nodiscard]] DoWhileStatementSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* DoKeyword, + const StatementSyntax* Body, + const SyntaxToken* WhileKeyword, + const ExpressionSyntax* Condition + ) noexcept; + + ~DoWhileStatementSyntax() noexcept override; SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::shared_ptr DoKeyword; - const std::shared_ptr Body; - const std::shared_ptr WhileKeyword; - const std::shared_ptr Condition; + const SyntaxToken* DoKeyword; + const StatementSyntax* Body; + const SyntaxToken* WhileKeyword; + const ExpressionSyntax* Condition; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/ElseClauseSyntax.cpp b/src/Mamba/Code Analysis/Syntax/ElseClauseSyntax.cpp index de7eba2..ff09d45 100644 --- a/src/Mamba/Code Analysis/Syntax/ElseClauseSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/ElseClauseSyntax.cpp @@ -1,24 +1,40 @@ #include "ElseClauseSyntax.h" -#include "StatementSyntax.h" -#include "SyntaxToken.h" +using namespace Mamba; -namespace Mamba +ElseClauseSyntax::ElseClauseSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* ElseKeyword, + const StatementSyntax* ElseStatement +) noexcept : + Super(SyntaxTree), ElseKeyword(ElseKeyword), ElseStatement(ElseStatement) { - ElseClauseSyntax::ElseClauseSyntax(const std::shared_ptr SyntaxTree, - const std::shared_ptr ElseKeyword, - const std::shared_ptr ElseStatement) noexcept : - Super(SyntaxTree), ElseKeyword(ElseKeyword), ElseStatement(ElseStatement) - { - } +} - SyntaxKind ElseClauseSyntax::Kind() const noexcept - { - return SyntaxKind::ElseClause; - } +ElseClauseSyntax::~ElseClauseSyntax() noexcept +{ + delete ElseStatement; +} - std::vector> ElseClauseSyntax::Children() const noexcept +SyntaxKind ElseClauseSyntax::Kind() const noexcept +{ + return SyntaxKind::ElseClause; +} + +std::size_t ElseClauseSyntax::ChildrenCount() const noexcept +{ + return 2; +} + +const SyntaxNode* ElseClauseSyntax::ChildAt(std::size_t Index) const noexcept +{ + switch (Index) { - return { ElseKeyword, ElseStatement }; + case 0: + return ElseKeyword; + case 1: + return ElseStatement; + default: + ReportChildrenAccessOutOfBounds(Index); } -} // namespace Mamba \ No newline at end of file +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/ElseClauseSyntax.h b/src/Mamba/Code Analysis/Syntax/ElseClauseSyntax.h index 6b2ce08..2480047 100644 --- a/src/Mamba/Code Analysis/Syntax/ElseClauseSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/ElseClauseSyntax.h @@ -1,10 +1,9 @@ #pragma once +#include "StatementSyntax.h" #include "SyntaxNode.h" #include "SyntaxToken.h" -#include - namespace Mamba { class ElseClauseSyntax : public SyntaxNode @@ -12,14 +11,21 @@ namespace Mamba public: using Super = SyntaxNode; - [[nodiscard]] ElseClauseSyntax(const std::shared_ptr SyntaxTree, - const std::shared_ptr ElseKeyword, - const std::shared_ptr ElseStatement) noexcept; + [[nodiscard]] ElseClauseSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* ElseKeyword, + const StatementSyntax* ElseStatement + ) noexcept; + + ~ElseClauseSyntax() noexcept override; SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::shared_ptr ElseKeyword; - const std::shared_ptr ElseStatement; + const SyntaxToken* ElseKeyword; + const StatementSyntax* ElseStatement; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/ExpressionStatementSyntax.cpp b/src/Mamba/Code Analysis/Syntax/ExpressionStatementSyntax.cpp index 38f0302..a36cf3d 100644 --- a/src/Mamba/Code Analysis/Syntax/ExpressionStatementSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/ExpressionStatementSyntax.cpp @@ -2,22 +2,37 @@ #include "ExpressionSyntax.h" -namespace Mamba +using namespace Mamba; + +ExpressionStatementSyntax::ExpressionStatementSyntax( + const class SyntaxTree* SyntaxTree, + const ExpressionSyntax* Expression +) noexcept : + Super(SyntaxTree), Expression(Expression) { - ExpressionStatementSyntax::ExpressionStatementSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr Expression) noexcept : - Super(SyntaxTree), Expression(Expression) - { - } +} - SyntaxKind ExpressionStatementSyntax::Kind() const noexcept - { - return SyntaxKind::ExpressionStatement; - } +ExpressionStatementSyntax::~ExpressionStatementSyntax() noexcept +{ + delete Expression; +} - std::vector> ExpressionStatementSyntax::Children() const noexcept +SyntaxKind ExpressionStatementSyntax::Kind() const noexcept +{ + return SyntaxKind::ExpressionStatement; +} + +std::size_t ExpressionStatementSyntax::ChildrenCount() const noexcept +{ + return 1; +} + +const SyntaxNode* ExpressionStatementSyntax::ChildAt(std::size_t Index) const noexcept +{ + if (Index != 0) { - return { Expression }; + ReportChildrenAccessOutOfBounds(Index); } -} // namespace Mamba \ No newline at end of file + + return Expression; +} diff --git a/src/Mamba/Code Analysis/Syntax/ExpressionStatementSyntax.h b/src/Mamba/Code Analysis/Syntax/ExpressionStatementSyntax.h index ce80445..0e8f5cc 100644 --- a/src/Mamba/Code Analysis/Syntax/ExpressionStatementSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/ExpressionStatementSyntax.h @@ -1,10 +1,9 @@ #pragma once +#include "ExpressionSyntax.h" #include "StatementSyntax.h" #include "SyntaxKind.h" -#include - namespace Mamba { class ExpressionStatementSyntax : public StatementSyntax @@ -13,12 +12,18 @@ namespace Mamba using Super = StatementSyntax; [[nodiscard]] ExpressionStatementSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr Expression) noexcept; + const class SyntaxTree* SyntaxTree, + const ExpressionSyntax* Expression + ) noexcept; + + ~ExpressionStatementSyntax() noexcept override; SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::shared_ptr Expression; + const ExpressionSyntax* Expression; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/ExpressionSyntax.cpp b/src/Mamba/Code Analysis/Syntax/ExpressionSyntax.cpp index fc212c9..d516806 100644 --- a/src/Mamba/Code Analysis/Syntax/ExpressionSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/ExpressionSyntax.cpp @@ -4,7 +4,7 @@ namespace Mamba { - ExpressionSyntax::ExpressionSyntax(const std::shared_ptr SyntaxTree) noexcept : + ExpressionSyntax::ExpressionSyntax(const class SyntaxTree* SyntaxTree) noexcept : Super(SyntaxTree) { } diff --git a/src/Mamba/Code Analysis/Syntax/ExpressionSyntax.h b/src/Mamba/Code Analysis/Syntax/ExpressionSyntax.h index 60f6329..6411c37 100644 --- a/src/Mamba/Code Analysis/Syntax/ExpressionSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/ExpressionSyntax.h @@ -10,6 +10,6 @@ namespace Mamba using Super = SyntaxNode; protected: - [[nodiscard]] ExpressionSyntax(const std::shared_ptr SyntaxTree) noexcept; + [[nodiscard]] ExpressionSyntax(const class SyntaxTree* SyntaxTree) noexcept; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/ForStatementSyntax.cpp b/src/Mamba/Code Analysis/Syntax/ForStatementSyntax.cpp index 6f64827..7682ddb 100644 --- a/src/Mamba/Code Analysis/Syntax/ForStatementSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/ForStatementSyntax.cpp @@ -3,42 +3,74 @@ #include "ExpressionSyntax.h" #include "StatementSyntax.h" -namespace Mamba +using namespace Mamba; + +ForStatementSyntax::ForStatementSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* Keyword, + const SyntaxToken* OpenParenthesisToken, + const StatementSyntax* InitStatement, + const SyntaxToken* InitStatementColonToken, + const ExpressionSyntax* Condition, + const SyntaxToken* ConditionColonToken, + const ExpressionSyntax* Expression, + const SyntaxToken* CloseParenthesisToken, + const StatementSyntax* Body +) noexcept : + Super(SyntaxTree), + Keyword(Keyword), + OpenParenthesisToken(OpenParenthesisToken), + InitStatement(InitStatement), + InitStatementColonToken(InitStatementColonToken), + Condition(Condition), + ConditionColonToken(ConditionColonToken), + Expression(Expression), + CloseParenthesisToken(CloseParenthesisToken), + Body(Body) { - ForStatementSyntax::ForStatementSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr Keyword, - const std::shared_ptr OpenParenthesisToken, - const std::shared_ptr InitStatement, - const std::shared_ptr InitStatementColonToken, - const std::shared_ptr Condition, - const std::shared_ptr ConditionColonToken, - const std::shared_ptr Expression, - const std::shared_ptr CloseParenthesisToken, - const std::shared_ptr Body - ) noexcept : - Super(SyntaxTree), - Keyword(Keyword), - OpenParenthesisToken(OpenParenthesisToken), - InitStatement(InitStatement), - InitStatementColonToken(InitStatementColonToken), - Condition(Condition), - ConditionColonToken(ConditionColonToken), - Expression(Expression), - CloseParenthesisToken(CloseParenthesisToken), - Body(Body) - { - } +} - SyntaxKind ForStatementSyntax::Kind() const noexcept - { - return SyntaxKind::ForStatement; - } +ForStatementSyntax::~ForStatementSyntax() noexcept +{ + delete InitStatement; + delete Condition; + delete Expression; + delete Body; +} - std::vector> ForStatementSyntax::Children() const noexcept +SyntaxKind ForStatementSyntax::Kind() const noexcept +{ + return SyntaxKind::ForStatement; +} + +std::size_t ForStatementSyntax::ChildrenCount() const noexcept +{ + return 9; +} + +const SyntaxNode* ForStatementSyntax::ChildAt(std::size_t Index) const noexcept +{ + switch (Index) { - return { Keyword, OpenParenthesisToken, InitStatement, InitStatementColonToken, - Condition, ConditionColonToken, Expression, CloseParenthesisToken, - Body }; + case 0: + return Keyword; + case 1: + return OpenParenthesisToken; + case 2: + return InitStatement; + case 3: + return InitStatementColonToken; + case 4: + return Condition; + case 5: + return ConditionColonToken; + case 6: + return Expression; + case 7: + return CloseParenthesisToken; + case 8: + return Body; + default: + ReportChildrenAccessOutOfBounds(Index); } -} // namespace Mamba \ No newline at end of file +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/ForStatementSyntax.h b/src/Mamba/Code Analysis/Syntax/ForStatementSyntax.h index 4ab8371..4cd465c 100644 --- a/src/Mamba/Code Analysis/Syntax/ForStatementSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/ForStatementSyntax.h @@ -1,9 +1,9 @@ #pragma once +#include "ExpressionSyntax.h" #include "StatementSyntax.h" #include "SyntaxToken.h" #include "SyntaxTree.h" -#include namespace Mamba { @@ -14,28 +14,35 @@ namespace Mamba public: using Super = StatementSyntax; - [[nodiscard]] ForStatementSyntax(const std::shared_ptr SyntaxTree, - const std::shared_ptr Keyword, - const std::shared_ptr OpenParenthesisToken, - const std::shared_ptr InitStatement, - const std::shared_ptr InitStatementColonToken, - const std::shared_ptr Condition, - const std::shared_ptr ConditionColonToken, - const std::shared_ptr Expression, - const std::shared_ptr CloseParenthesisToken, - const std::shared_ptr Body) noexcept; + [[nodiscard]] ForStatementSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* Keyword, + const SyntaxToken* OpenParenthesisToken, + const StatementSyntax* InitStatement, + const SyntaxToken* InitStatementColonToken, + const ExpressionSyntax* Condition, + const SyntaxToken* ConditionColonToken, + const ExpressionSyntax* Expression, + const SyntaxToken* CloseParenthesisToken, + const StatementSyntax* Body + ) noexcept; + + ~ForStatementSyntax() noexcept override; SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::shared_ptr Keyword; - const std::shared_ptr OpenParenthesisToken; - const std::shared_ptr InitStatement; - const std::shared_ptr InitStatementColonToken; - const std::shared_ptr Condition; - const std::shared_ptr ConditionColonToken; - const std::shared_ptr Expression; - const std::shared_ptr CloseParenthesisToken; - const std::shared_ptr Body; + const SyntaxToken* Keyword; + const SyntaxToken* OpenParenthesisToken; + const StatementSyntax* InitStatement; + const SyntaxToken* InitStatementColonToken; + const ExpressionSyntax* Condition; + const SyntaxToken* ConditionColonToken; + const ExpressionSyntax* Expression; + const SyntaxToken* CloseParenthesisToken; + const StatementSyntax* Body; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/FunctionDeclarationSyntax.cpp b/src/Mamba/Code Analysis/Syntax/FunctionDeclarationSyntax.cpp index 52530c0..1aa34d9 100644 --- a/src/Mamba/Code Analysis/Syntax/FunctionDeclarationSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/FunctionDeclarationSyntax.cpp @@ -1,57 +1,78 @@ #include "FunctionDeclarationSyntax.h" -#include "BlockStatementSyntax.h" -#include "ParameterSyntax.h" -#include "SyntaxToken.h" -#include "TypeClauseSyntax.h" +using namespace Mamba; -namespace Mamba +FunctionDeclarationSyntax::FunctionDeclarationSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* FunctionKeyword, + const SyntaxToken* Identifier, + const SyntaxToken* OpenParenthesisToken, + SeperatedSyntaxList&& Parameters, + const SyntaxToken* CloseParenthesisToken, + NullablePointer Type, + const BlockStatementSyntax* Body +) noexcept : + Super(SyntaxTree), + FunctionKeyword(FunctionKeyword), + Identifier(Identifier), + OpenParenthesisToken(OpenParenthesisToken), + Parameters(std::move(Parameters)), + CloseParenthesisToken(CloseParenthesisToken), + Type(Type), + Body(Body) { - FunctionDeclarationSyntax::FunctionDeclarationSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr FunctionKeyword, - const std::shared_ptr Identifier, - const std::shared_ptr OpenParenthesisToken, - const std::shared_ptr>> Parameters, - const std::shared_ptr CloseParenthesisToken, - const NullableSharedPtr Type, - const std::shared_ptr Body - ) noexcept : - Super(SyntaxTree), - FunctionKeyword(FunctionKeyword), - Identifier(Identifier), - OpenParenthesisToken(OpenParenthesisToken), - Parameters(Parameters), - CloseParenthesisToken(CloseParenthesisToken), - Type(Type), - Body(Body) - { - } +} - SyntaxKind FunctionDeclarationSyntax::Kind() const noexcept +FunctionDeclarationSyntax::~FunctionDeclarationSyntax() noexcept +{ + for (auto&& Parameter : Parameters.Nodes()) { - return SyntaxKind::FunctionDeclaration; + delete Parameter; } + delete Type; + delete Body; +} - std::vector> FunctionDeclarationSyntax::Children() const noexcept - { - auto Children = std::vector>(); - Children.reserve(6 + Parameters->Count() * 2); +SyntaxKind FunctionDeclarationSyntax::Kind() const noexcept +{ + return SyntaxKind::FunctionDeclaration; +} - Children.emplace_back(FunctionKeyword); - Children.emplace_back(Identifier); - Children.emplace_back(OpenParenthesisToken); - for (auto Parameter : Parameters->Nodes()) - { - Children.emplace_back(Parameter); - } - Children.emplace_back(CloseParenthesisToken); - if (Type) - { - Children.emplace_back(Type); - } - Children.emplace_back(Body); +std::size_t FunctionDeclarationSyntax::ChildrenCount() const noexcept +{ + return Type ? 6 : 5 + Parameters.size(); +} - return Children; +const SyntaxNode* FunctionDeclarationSyntax::ChildAt(std::size_t Index) const noexcept +{ + if (Index == 0) + { + return FunctionKeyword; } -} // namespace Mamba \ No newline at end of file + else if (Index == 1) + { + return Identifier; + } + else if (Index == 2) + { + return OpenParenthesisToken; + } + else if (Index < Parameters.size() + 3) + { + return Parameters[Index - 3]; + } + else if (Index == Parameters.size() + 3) + { + return CloseParenthesisToken; + } + else if (Index == Parameters.size() + 4) + { + return Type ? static_cast(Type) : Body; + } + else if (Index == Parameters.size() + 5 && Type) + { + return Body; + } + + ReportChildrenAccessOutOfBounds(Index); +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/FunctionDeclarationSyntax.h b/src/Mamba/Code Analysis/Syntax/FunctionDeclarationSyntax.h index ec0465e..951de39 100644 --- a/src/Mamba/Code Analysis/Syntax/FunctionDeclarationSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/FunctionDeclarationSyntax.h @@ -1,10 +1,12 @@ #pragma once +#include "BlockStatementSyntax.h" #include "MemberSyntax.h" +#include "ParameterSyntax.h" #include "SeperatedSyntaxList.h" #include "SyntaxKind.h" - -#include +#include "SyntaxToken.h" +#include "TypeClauseSyntax.h" namespace Mamba { @@ -14,25 +16,30 @@ namespace Mamba using Super = MemberSyntax; [[nodiscard]] FunctionDeclarationSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr FunctionKeyword, - const std::shared_ptr Identifier, - const std::shared_ptr OpenParenthesisToken, - const std::shared_ptr>> Parameters, - const std::shared_ptr CloseParenthesisToken, - const NullableSharedPtr Type, - const std::shared_ptr Body + const class SyntaxTree* SyntaxTree, + const SyntaxToken* FunctionKeyword, + const SyntaxToken* Identifier, + const SyntaxToken* OpenParenthesisToken, + SeperatedSyntaxList&& Parameters, + const SyntaxToken* CloseParenthesisToken, + NullablePointer Type, + const BlockStatementSyntax* Body ) noexcept; + ~FunctionDeclarationSyntax() noexcept override; + SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::shared_ptr FunctionKeyword; - const std::shared_ptr Identifier; - const std::shared_ptr OpenParenthesisToken; - const std::shared_ptr>> Parameters; - const std::shared_ptr CloseParenthesisToken; - const NullableSharedPtr Type; - const std::shared_ptr Body; + const SyntaxToken* FunctionKeyword; + const SyntaxToken* Identifier; + const SyntaxToken* OpenParenthesisToken; + SeperatedSyntaxList Parameters; + const SyntaxToken* CloseParenthesisToken; + NullablePointer Type; + const BlockStatementSyntax* Body; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/GlobalStatementSyntax.cpp b/src/Mamba/Code Analysis/Syntax/GlobalStatementSyntax.cpp index e9f8f47..9fb8452 100644 --- a/src/Mamba/Code Analysis/Syntax/GlobalStatementSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/GlobalStatementSyntax.cpp @@ -2,22 +2,37 @@ #include "StatementSyntax.h" -namespace Mamba +using namespace Mamba; + +GlobalStatementSyntax::GlobalStatementSyntax( + const class SyntaxTree* SyntaxTree, + const StatementSyntax* Statement +) noexcept : + Super(SyntaxTree), Statement(Statement) { - GlobalStatementSyntax::GlobalStatementSyntax(const std::shared_ptr SyntaxTree, - const std::shared_ptr Statement) noexcept - : - Super(SyntaxTree), Statement(Statement) - { - } +} - SyntaxKind GlobalStatementSyntax::Kind() const noexcept - { - return SyntaxKind::GlobalStatement; - } +GlobalStatementSyntax::~GlobalStatementSyntax() noexcept +{ + delete Statement; +} - std::vector> GlobalStatementSyntax::Children() const noexcept +SyntaxKind GlobalStatementSyntax::Kind() const noexcept +{ + return SyntaxKind::GlobalStatement; +} + +std::size_t GlobalStatementSyntax::ChildrenCount() const noexcept +{ + return 1; +} + +const SyntaxNode* GlobalStatementSyntax::ChildAt(std::size_t Index) const noexcept +{ + if (Index != 0) { - return { Statement }; + ReportChildrenAccessOutOfBounds(Index); } -} // namespace Mamba \ No newline at end of file + + return Statement; +} diff --git a/src/Mamba/Code Analysis/Syntax/GlobalStatementSyntax.h b/src/Mamba/Code Analysis/Syntax/GlobalStatementSyntax.h index ef21eac..1ed57a1 100644 --- a/src/Mamba/Code Analysis/Syntax/GlobalStatementSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/GlobalStatementSyntax.h @@ -1,8 +1,8 @@ #pragma once #include "MemberSyntax.h" +#include "StatementSyntax.h" #include "SyntaxTree.h" -#include namespace Mamba { @@ -11,12 +11,19 @@ namespace Mamba public: using Super = MemberSyntax; - [[nodiscard]] GlobalStatementSyntax(const std::shared_ptr SyntaxTree, - const std::shared_ptr Statement) noexcept; + [[nodiscard]] GlobalStatementSyntax( + const class SyntaxTree* SyntaxTree, + const StatementSyntax* Statement + ) noexcept; + + ~GlobalStatementSyntax() noexcept override; SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::shared_ptr Statement; + const StatementSyntax* Statement; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/IfStatementSyntax.cpp b/src/Mamba/Code Analysis/Syntax/IfStatementSyntax.cpp index c4f5d99..0072994 100644 --- a/src/Mamba/Code Analysis/Syntax/IfStatementSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/IfStatementSyntax.cpp @@ -1,69 +1,56 @@ #include "IfStatementSyntax.h" -#include "ElseClauseSyntax.h" -#include "ExpressionSyntax.h" +using namespace Mamba; -namespace Mamba +IfStatementSyntax::IfStatementSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* IfKeyword, + const ExpressionSyntax* Condition, + const StatementSyntax* ThenStatement, + NullablePointer ElseClause +) noexcept : + Super(SyntaxTree), + IfKeyword(IfKeyword), + Condition(Condition), + ThenStatement(ThenStatement), + ElseClause(ElseClause) { - IfStatementSyntax::IfStatementSyntax(const std::shared_ptr SyntaxTree, - const std::shared_ptr IfKeyword, - const NullableSharedPtr OpenParenthesisToken, - const std::shared_ptr Condition, - const NullableSharedPtr CloseParenthesisToken, - const std::shared_ptr ThenStatement, - const NullableSharedPtr ElseClause) noexcept : - Super(SyntaxTree), - IfKeyword(IfKeyword), - OpenParenthesisToken(OpenParenthesisToken), - Condition(Condition), - CloseParenthesisToken(CloseParenthesisToken), - ThenStatement(ThenStatement), - ElseClause(ElseClause) - { - } - - SyntaxKind IfStatementSyntax::Kind() const noexcept - { - return SyntaxKind::IfStatement; - } +} - std::vector> IfStatementSyntax::Children() const noexcept - { - // Calculates the number of children, in for statement, parentheses and else clause are optional, - // so there are at least 3 children - auto ChildrenCount = 3; - if (OpenParenthesisToken) - { - ++ChildrenCount; - } - if (CloseParenthesisToken) - { - ++ChildrenCount; - } - if (ElseClause) - { - ++ChildrenCount; - } +IfStatementSyntax::~IfStatementSyntax() noexcept +{ + delete Condition; + delete ThenStatement; + delete ElseClause; +} - auto Children = std::vector>(); - Children.reserve(ChildrenCount); +SyntaxKind IfStatementSyntax::Kind() const noexcept +{ + return SyntaxKind::IfStatement; +} - Children.emplace_back(IfKeyword); - if (OpenParenthesisToken) - { - Children.emplace_back(OpenParenthesisToken); - } - Children.emplace_back(Condition); - if (CloseParenthesisToken) - { - Children.emplace_back(CloseParenthesisToken); - } - Children.emplace_back(ThenStatement); - if (ElseClause) - { - Children.emplace_back(ElseClause); - } +std::size_t IfStatementSyntax::ChildrenCount() const noexcept +{ + return ElseClause ? 3 : 4; +} - return Children; +const SyntaxNode* IfStatementSyntax::ChildAt(std::size_t Index) const noexcept +{ + switch (Index) + { + case 0: + return IfKeyword; + case 1: + return Condition; + case 2: + return ThenStatement; + case 3: + if (ElseClause) + { + return ElseClause; + } + [[fallthrough]]; + default: + ReportChildrenAccessOutOfBounds(Index); } -} // namespace Mamba \ No newline at end of file +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/IfStatementSyntax.h b/src/Mamba/Code Analysis/Syntax/IfStatementSyntax.h index bef92d9..9906f19 100644 --- a/src/Mamba/Code Analysis/Syntax/IfStatementSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/IfStatementSyntax.h @@ -1,8 +1,9 @@ #pragma once +#include "ElseClauseSyntax.h" +#include "ExpressionSyntax.h" #include "StatementSyntax.h" - -#include +#include "SyntaxToken.h" namespace Mamba { @@ -11,22 +12,25 @@ namespace Mamba public: using Super = StatementSyntax; - [[nodiscard]] IfStatementSyntax(const std::shared_ptr SyntaxTree, - const std::shared_ptr IfKeyword, - const NullableSharedPtr OpenParenthesisToken, - const std::shared_ptr Condition, - const NullableSharedPtr CloseParenthesisToken, - const std::shared_ptr ThenStatement, - const NullableSharedPtr ElseClause) noexcept; + [[nodiscard]] IfStatementSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* IfKeyword, + const ExpressionSyntax* Condition, + const StatementSyntax* ThenStatement, + NullablePointer ElseClause + ) noexcept; + + ~IfStatementSyntax() noexcept override; SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::shared_ptr IfKeyword; - const NullableSharedPtr OpenParenthesisToken; - const std::shared_ptr Condition; - const NullableSharedPtr CloseParenthesisToken; - const std::shared_ptr ThenStatement; - const NullableSharedPtr ElseClause; + const SyntaxToken* IfKeyword; + const ExpressionSyntax* Condition; + const StatementSyntax* ThenStatement; + NullablePointer ElseClause; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/Lexer.cpp b/src/Mamba/Code Analysis/Syntax/Lexer.cpp index c19616b..0aca2cc 100644 --- a/src/Mamba/Code Analysis/Syntax/Lexer.cpp +++ b/src/Mamba/Code Analysis/Syntax/Lexer.cpp @@ -1,45 +1,38 @@ #include "Lexer.h" #include "DiagnosticBag.h" +#include "fast_io.h" #include "Literal.h" #include "SourceText.h" #include "SyntaxFacts.h" #include "SyntaxKind.h" #include "SyntaxToken.h" #include "SyntaxTree.h" -#include "TextLocation.h" -#include "TextSpan.h" - -#include -#include -#include namespace Mamba { - Lexer::Lexer(const std::shared_ptr SyntaxTree) : - SyntaxTree(SyntaxTree), Text(SyntaxTree->Text), Position(), Start(), Kind(SyntaxKind::BadToken) + Lexer::Lexer(const class SyntaxTree* SyntaxTree) : + SyntaxTree(SyntaxTree), Position(), Start(), Kind(SyntaxKind::BadToken) { } - std::shared_ptr Lexer::Lex() noexcept + SyntaxToken Lexer::Lex() noexcept { - const auto TokenStart = Position; + auto TokenStart = Position; ReadToken(); - const auto TokenKind = Kind; - const auto TokenValue = Value; - const auto TokenLength = Position - Start; + auto TokenValue = Value; + auto TokenLength = Position - Start; - auto TokenText = - std::make_shared(Hatcher([&] - { return String(SyntaxFacts::GetText(TokenKind)); })); - if (TokenText->empty()) - { - TokenText = Text->ToString(TokenStart, TokenLength); - } + auto TokenText = Text().SubView(TokenStart, TokenLength); + + return SyntaxToken(SyntaxTree, Kind, TokenText, TokenValue); + } - return std::make_shared(SyntaxTree, Kind, TokenStart, TokenText, TokenValue); + const SourceText& Lexer::Text() const noexcept + { + return SyntaxTree->Text(); } Char Lexer::Current() const noexcept @@ -52,22 +45,22 @@ namespace Mamba return Peek(1); } - Char Lexer::Peek(const std::size_t Offset) const noexcept + Char Lexer::Peek(std::size_t Offset) const noexcept { - const auto Index = Position + Offset; - if (Index >= Text->Length()) + auto Index = Position + Offset; + if (Index >= Text().Length()) { return '\0'; } - return (*Text)[Index]; + return Text()[Index]; } void Lexer::ReadToken() noexcept { Start = Position; Kind = SyntaxKind::BadToken; - Value = nullptr; + Value = {}; switch (Current()) { @@ -275,8 +268,9 @@ namespace Mamba } else { - const auto Span = TextSpan(Position, 1); - const auto Location = TextLocation(Text, Span); + auto View = Text().SubView(Position, 1); + auto Location = TextLocation(Text(), View); + Diagnostics.ReportInvalidCharacter(Location, Current()); ++Position; } @@ -298,8 +292,8 @@ namespace Mamba case TEXT('\r'): case TEXT('\n'): { - const auto Span = TextSpan(Start, 1); - const auto Location = TextLocation(Text, Span); + auto View = Text().SubView(Position, 1); + auto Location = TextLocation(Text(), View); Diagnostics.ReportUnterminatedString(Location); Done = true; break; @@ -321,10 +315,10 @@ namespace Mamba } } - const auto Length = Position - Start; + auto Length = Position - Start; Kind = SyntaxKind::StringToken; - Value = std::make_shared(Literal(Text->ToString(Start + 1, Length - 2))); + Value = Text().SubView(Start + 1, Length - 2); } void Lexer::ReadIdentifierOrKeyword() noexcept @@ -334,15 +328,17 @@ namespace Mamba ++Position; } - const auto Length = Position - Start; - const auto Span = TextSpan(Start, Length); - const auto Text = this->Text->ToView(Span); + auto Length = Position - Start; + auto Text = this->Text().SubView(Start, Length); Kind = SyntaxFacts::GetKeywordKind(Text); } void Lexer::ReadWhitespace() noexcept { - while (Current() == TEXT(' ') || Current() == TEXT('\n') || Current() == TEXT('\t') || Current() == TEXT('\r')) + while (Current() == TEXT(' ') || + Current() == TEXT('\n') || + Current() == TEXT('\t') || + Current() == TEXT('\r')) { ++Position; } @@ -384,10 +380,9 @@ namespace Mamba ++Position; } - const auto Length = Position - Start; - const auto Span = TextSpan(Start, Length); - const auto Number = ParseNumber<10>(Span); - NarrowNumber(Number); + auto Length = Position - Start; + auto View = Text().SubView(Start, Length); + Value = ParseNumber<10>(View); } void Lexer::ReadHexadecimal() noexcept @@ -398,10 +393,9 @@ namespace Mamba } // Skip the '0x' or '0X' character sequence - const auto Length = Position - Start; - const auto Span = TextSpan(Start + 2, Length); - const auto Number = ParseNumber<16>(Span); - NarrowNumber(Number); + auto Length = Position - Start; + auto View = Text().SubView(Start + 2, Length); + Value = ParseNumber<16>(View); } void Lexer::ReadBinary() noexcept @@ -412,10 +406,9 @@ namespace Mamba } // Skip the '0b' or '0B' character sequence - const auto Length = Position - Start; - const auto Span = TextSpan(Start + 2, Length); - const auto Number = ParseNumber<2>(Span); - NarrowNumber(Number); + auto Length = Position - Start; + auto View = Text().SubView(Start + 2, Length); + Value = ParseNumber<2>(View); } void Lexer::ReadOctal() noexcept @@ -426,56 +419,41 @@ namespace Mamba } // Skip the 0 prefix - const auto Length = Position - Start; - const auto Span = TextSpan(Start + 1, Length); - const auto Number = ParseNumber<8>(Span); - NarrowNumber(Number); + auto Length = Position - Start; + auto View = Text().SubView(Start + 1, Length); + Value = ParseNumber<8>(View); } - bool Lexer::IsLetter(const Char Character) noexcept + bool Lexer::IsLetter(Char Character) noexcept { - return (Character >= TEXT('a') && Character <= TEXT('z')) || (Character >= TEXT('A') && Character <= TEXT('Z')); + return (Character >= TEXT('a') && Character <= TEXT('z')) || + (Character >= TEXT('A') && Character <= TEXT('Z')); } - bool Lexer::IsLetterOrDigit(const Char Character) noexcept + bool Lexer::IsLetterOrDigit(Char Character) noexcept { return IsLetter(Character) || IsDecimalDigit(Character); } - bool Lexer::IsDecimalDigit(const Char Character) noexcept + bool Lexer::IsDecimalDigit(Char Character) noexcept { return Character >= TEXT('0') && Character <= TEXT('9'); } - bool Lexer::IsHexadecimalDigit(const Char Character) noexcept + bool Lexer::IsHexadecimalDigit(Char Character) noexcept { - return (Character >= TEXT('0') && Character <= TEXT('9')) || (Character >= TEXT('a') && Character <= TEXT('f')) || (Character >= TEXT('A') && Character <= TEXT('F')); + return (Character >= TEXT('0') && Character <= TEXT('9')) || + (Character >= TEXT('a') && Character <= TEXT('f')) || + (Character >= TEXT('A') && Character <= TEXT('F')); } - bool Lexer::IsBinaryDigit(const Char Character) noexcept + bool Lexer::IsBinaryDigit(Char Character) noexcept { return Character == TEXT('0') || Character == TEXT('1'); } - bool Lexer::IsOctalDigit(const Char Character) noexcept + bool Lexer::IsOctalDigit(Char Character) noexcept { return Character >= TEXT('0') && Character <= TEXT('7'); } - - void Lexer::NarrowNumber(const std::uint64_t Value) noexcept - { - // Literals can be represented by int32 if they are capable of being represented by int32, - // otherwise they are int64. If the literal represents a value outside the range of int64, - // it is represented by unsigned int64, otherwise diagnostics are required. - if (Value <= std::numeric_limits::max()) - { - this->Value = std::make_shared(static_cast(Value)); - } - else if (Value <= std::numeric_limits::max()) - { - this->Value = std::make_shared(static_cast(Value)); - } - - this->Value = std::make_shared(Value); - } } // namespace Mamba diff --git a/src/Mamba/Code Analysis/Syntax/Lexer.h b/src/Mamba/Code Analysis/Syntax/Lexer.h index b026e46..1b9508d 100644 --- a/src/Mamba/Code Analysis/Syntax/Lexer.h +++ b/src/Mamba/Code Analysis/Syntax/Lexer.h @@ -1,37 +1,37 @@ #pragma once #include "DiagnosticBag.h" +#include "Literal.h" #include "MambaCore.h" #include "SourceText.h" #include "SyntaxKind.h" -#include "TextSpan.h" - -#include +#include "SyntaxToken.h" namespace Mamba { class Lexer { - const std::shared_ptr SyntaxTree; - const std::shared_ptr Text; + const class SyntaxTree* SyntaxTree; std::size_t Position; std::size_t Start; SyntaxKind Kind; - NullableSharedPtr Value; + Literal Value; public: DiagnosticBag Diagnostics; - [[nodiscard]] Lexer(const std::shared_ptr SyntaxTree); + [[nodiscard]] Lexer(const class SyntaxTree* SyntaxTree); - [[nodiscard]] std::shared_ptr Lex() noexcept; + [[nodiscard]] SyntaxToken Lex() noexcept; private: + const SourceText& Text() const noexcept; + [[nodiscard]] Char Current() const noexcept; [[nodiscard]] Char Lookahead() const noexcept; - [[nodiscard]] Char Peek(const std::size_t Offset) const noexcept; + [[nodiscard]] Char Peek(std::size_t Offset) const noexcept; void ReadToken() noexcept; void ReadString() noexcept; @@ -44,65 +44,53 @@ namespace Mamba void ReadBinary() noexcept; void ReadOctal() noexcept; - [[nodiscard]] static bool IsLetter(const Char Character) noexcept; - [[nodiscard]] static bool IsLetterOrDigit(const Char Character) noexcept; - [[nodiscard]] static bool IsDecimalDigit(const Char Character) noexcept; - [[nodiscard]] static bool IsHexadecimalDigit(const Char Character) noexcept; - [[nodiscard]] static bool IsBinaryDigit(const Char Character) noexcept; - [[nodiscard]] static bool IsOctalDigit(const Char Character) noexcept; - - // Narrow down the supplied number, choose the smallest type that can represent it, - // and save it to the member variable 'Value'. - void NarrowNumber(const std::uint64_t Value) noexcept; + [[nodiscard]] static bool IsLetter(Char Character) noexcept; + [[nodiscard]] static bool IsLetterOrDigit(Char Character) noexcept; + [[nodiscard]] static bool IsDecimalDigit(Char Character) noexcept; + [[nodiscard]] static bool IsHexadecimalDigit(Char Character) noexcept; + [[nodiscard]] static bool IsBinaryDigit(Char Character) noexcept; + [[nodiscard]] static bool IsOctalDigit(Char Character) noexcept; // Parse a literal number with a specified base, diagnostics are required if any error occurs. template - [[nodiscard]] std::uint64_t ParseNumber(const TextSpan Span) noexcept + [[nodiscard]] std::uint64_t ParseNumber(StringView LiteralText) noexcept requires(Base == 2 || Base == 8 || Base == 10 || Base == 16) { - const auto Literal = Text->ToView(Span); - auto Result = 0ULL; -#ifdef MAMBA_NO_EXCEPTIONS - fast_io::io::scan(fast_io::basic_ibuffer_view(Literal), fast_io::mnp::base_get(Result)); -#else try { - fast_io::io::scan(fast_io::basic_ibuffer_view(Literal), fast_io::mnp::base_get(Result)); + fast_io::io::scan(fast_io::basic_ibuffer_view(LiteralText), fast_io::mnp::base_get(Result)); } - catch (const fast_io::error& error) + catch (fast_io::error error) { - ReportInvalidNumber(Span, Literal); - fast_io::io::perrln(error); + ReportInvalidNumber(LiteralText); } -#endif return Result; } // Report an invalid number diagnostic with the specified base and literal template - void ReportInvalidNumber(const TextSpan Span, const StringView Literal) - + void ReportInvalidNumber(StringView LiteralText) requires(Base == 2 || Base == 8 || Base == 10 || Base == 16) { - const auto Location = TextLocation(Text, Span); + const auto Location = TextLocation(Text(), LiteralText); if constexpr (Base == 10) { - Diagnostics.ReportInvalidDecimal(Location, Literal); + Diagnostics.ReportInvalidDecimal(Location, LiteralText); } else if constexpr (Base == 16) { - Diagnostics.ReportInvalidHexadecimal(Location, Literal); + Diagnostics.ReportInvalidHexadecimal(Location, LiteralText); } else if constexpr (Base == 2) { - Diagnostics.ReportInvalidBinary(Location, Literal); + Diagnostics.ReportInvalidBinary(Location, LiteralText); } else if constexpr (Base == 8) { - Diagnostics.ReportInvalidOctal(Location, Literal); + Diagnostics.ReportInvalidOctal(Location, LiteralText); } } }; diff --git a/src/Mamba/Code Analysis/Syntax/Literal.cpp b/src/Mamba/Code Analysis/Syntax/Literal.cpp deleted file mode 100644 index e7a1dee..0000000 --- a/src/Mamba/Code Analysis/Syntax/Literal.cpp +++ /dev/null @@ -1,696 +0,0 @@ -#include "Literal.h" - -#include - -#include "MambaCore.h" - -using namespace Mamba; - -LiteralValue::LiteralValue() noexcept {} - -LiteralValue::LiteralValue(const StringView String) noexcept : - StringValue(String) {} - -LiteralValue::LiteralValue(const std::int8_t Integer) noexcept : - SignedByteValue(Integer) {} - -LiteralValue::LiteralValue(const std::int16_t Integer) noexcept : - SignedShortValue(Integer) {} - -LiteralValue::LiteralValue(const std::int32_t Integer) noexcept : - SignedIntValue(Integer) {} - -LiteralValue::LiteralValue(const std::int64_t Integer) noexcept : - SignedLongValue(Integer) {} - -LiteralValue::LiteralValue(const std::uint8_t Integer) noexcept : - UnsignedShortValue(Integer) {} - -LiteralValue::LiteralValue(const std::uint16_t Integer) noexcept : - UnsignedShortValue(Integer) {} - -LiteralValue::LiteralValue(const std::uint32_t Integer) noexcept : - UnsignedIntValue(Integer) {} - -LiteralValue::LiteralValue(const std::uint64_t Integer) noexcept : - UnsignedLongValue(Integer) {} - -LiteralValue::LiteralValue(const float Value) noexcept : - FloatValue(Value) {} - -LiteralValue::LiteralValue(const double Value) noexcept : - DoubleValue(Value) {} - -LiteralValue::LiteralValue(const bool Value) noexcept : - BooleanValue(Value) {} - -Literal::Literal() noexcept {} - -Literal::Literal(const std::shared_ptr String) noexcept : - Value(StringView(*String)), Type(LiteralType::String), StringValue(String) -{ -} - -Literal::Literal(const std::int8_t Integer) noexcept : - Value(Integer), Type(LiteralType::SignedByte) {} - -Literal::Literal(const std::int32_t Integer) noexcept : - Value(Integer), Type(LiteralType::SignedInt) {} - -Literal::Literal(const std::int64_t Integer) noexcept : - Value(Integer), Type(LiteralType::SignedLong) {} - -Literal::Literal(const std::uint8_t Integer) noexcept : - Value(Integer), Type(LiteralType::UnsignedByte) {} - -Literal::Literal(const std::uint16_t Integer) noexcept : - Value(Integer), Type(LiteralType::UnsignedShort) {} - -Literal::Literal(const std::uint32_t Integer) noexcept : - Value(Integer), Type(LiteralType::UnsignedInt) {} - -Literal::Literal(const std::uint64_t Integer) noexcept : - Value(Integer), Type(LiteralType::UnsignedLong) {} - -Literal::Literal(const Char Character) noexcept : - Value(Character), Type(LiteralType::Character) {} - -Literal::Literal(const float Value) noexcept : - Value(Value), Type(LiteralType::Float) {} - -Literal::Literal(const double Value) noexcept : - Value(Value), Type(LiteralType::Double) {} - -Literal::Literal(const bool Value) noexcept : - Value(Value), Type(LiteralType::Boolean) {} - -NullableSharedPtr Literal::Negative(const Literal& Literal) noexcept -{ - switch (Literal.Type) - { - case LiteralType::SignedByte: - return std::make_shared(-Literal.Value.SignedByteValue); - case LiteralType::SignedShort: - return std::make_shared(-Literal.Value.SignedShortValue); - case LiteralType::SignedInt: - return std::make_shared(-Literal.Value.SignedIntValue); - case LiteralType::SignedLong: - return std::make_shared(-Literal.Value.SignedLongValue); - case LiteralType::Double: - return std::make_shared(-Literal.Value.DoubleValue); - case LiteralType::Float: - return std::make_shared(-Literal.Value.FloatValue); - - case LiteralType::String: - case LiteralType::Character: - case LiteralType::UnsignedByte: - case LiteralType::UnsignedShort: - case LiteralType::UnsignedInt: - case LiteralType::UnsignedLong: - case LiteralType::Boolean: - case LiteralType::Empty: - default: - return {}; - } -} - -NullableSharedPtr Literal::LogicalNegative(const Literal& Literal) noexcept -{ - switch (Literal.Type) - { - case LiteralType::Boolean: - return std::make_shared(!Literal.Value.BooleanValue); - - case LiteralType::SignedByte: - case LiteralType::SignedShort: - case LiteralType::SignedInt: - case LiteralType::SignedLong: - case LiteralType::Double: - case LiteralType::Float: - case LiteralType::String: - case LiteralType::Character: - case LiteralType::UnsignedByte: - case LiteralType::UnsignedShort: - case LiteralType::UnsignedInt: - case LiteralType::UnsignedLong: - case LiteralType::Empty: - default: - return {}; - } -} - -NullableSharedPtr Literal::OnesComplement(const Literal& Literal) noexcept -{ - switch (Literal.Type) - { - case LiteralType::UnsignedByte: - return std::make_shared(~Literal.Value.UnsignedByteValue); - case LiteralType::UnsignedShort: - return std::make_shared(~Literal.Value.UnsignedShortValue); - case LiteralType::UnsignedInt: - return std::make_shared(~Literal.Value.UnsignedIntValue); - case LiteralType::UnsignedLong: - return std::make_shared(~Literal.Value.UnsignedLongValue); - case LiteralType::SignedByte: - return std::make_shared(~Literal.Value.SignedByteValue); - case LiteralType::SignedShort: - return std::make_shared(~Literal.Value.SignedShortValue); - case LiteralType::SignedInt: - return std::make_shared(~Literal.Value.SignedIntValue); - case LiteralType::SignedLong: - return std::make_shared(~Literal.Value.SignedLongValue); - - case LiteralType::Double: - case LiteralType::Float: - case LiteralType::String: - case LiteralType::Character: - case LiteralType::Empty: - case LiteralType::Boolean: - default: - return {}; - } -} - -static void MatchOperandType(const LiteralType Left, const LiteralType Right) noexcept -{ - if (Left != Right) - { -#ifdef DEBUG - fast_io::io::perrln( - "Operand type not match, ", - static_cast(Left), - " != ", - static_cast(Right) - ); -#endif - std::unreachable(); - } -} - -NullableSharedPtr Literal::operator+(const Literal& Other) const noexcept -{ - MatchOperandType(Type, Other.Type); - switch (Type) - { - case LiteralType::String: - return std::make_shared(Hatcher( - [&] - { return std::make_shared(Concat(Value.StringValue, Other.Value.StringValue)); } - )); - case LiteralType::UnsignedByte: - return std::make_shared(Value.UnsignedByteValue + Other.Value.UnsignedByteValue); - case LiteralType::UnsignedShort: - return std::make_shared(Value.UnsignedShortValue + Other.Value.UnsignedShortValue); - case LiteralType::UnsignedInt: - return std::make_shared(Value.UnsignedIntValue + Other.Value.UnsignedIntValue); - case LiteralType::UnsignedLong: - return std::make_shared(Value.UnsignedLongValue + Other.Value.UnsignedLongValue); - case LiteralType::SignedByte: - return std::make_shared(Value.SignedByteValue + Other.Value.SignedByteValue); - case LiteralType::SignedShort: - return std::make_shared(Value.SignedShortValue + Other.Value.SignedShortValue); - case LiteralType::SignedInt: - return std::make_shared(Value.SignedIntValue + Other.Value.SignedIntValue); - case LiteralType::SignedLong: - return std::make_shared(Value.SignedLongValue + Other.Value.SignedLongValue); - case LiteralType::Double: - return std::make_shared(Value.DoubleValue + Other.Value.DoubleValue); - case LiteralType::Float: - return std::make_shared(Value.FloatValue + Other.Value.FloatValue); - case LiteralType::Character: - case LiteralType::Boolean: - case LiteralType::Empty: - default: - return {}; - } -} - -NullableSharedPtr Literal::operator-(const Literal& Other) const noexcept -{ - MatchOperandType(Type, Other.Type); - switch (Type) - { - case LiteralType::UnsignedByte: - return std::make_shared(Value.UnsignedByteValue - Other.Value.UnsignedByteValue); - case LiteralType::UnsignedShort: - return std::make_shared(Value.UnsignedShortValue - Other.Value.UnsignedShortValue); - case LiteralType::UnsignedInt: - return std::make_shared(Value.UnsignedIntValue - Other.Value.UnsignedIntValue); - case LiteralType::UnsignedLong: - return std::make_shared(Value.UnsignedLongValue - Other.Value.UnsignedLongValue); - case LiteralType::SignedByte: - return std::make_shared(Value.SignedByteValue - Other.Value.SignedByteValue); - case LiteralType::SignedShort: - return std::make_shared(Value.SignedShortValue - Other.Value.SignedShortValue); - case LiteralType::SignedInt: - return std::make_shared(Value.SignedIntValue - Other.Value.SignedIntValue); - case LiteralType::SignedLong: - return std::make_shared(Value.SignedLongValue - Other.Value.SignedLongValue); - case LiteralType::Double: - return std::make_shared(Value.DoubleValue - Other.Value.DoubleValue); - case LiteralType::Float: - return std::make_shared(Value.FloatValue - Other.Value.FloatValue); - - case LiteralType::String: - case LiteralType::Character: - case LiteralType::Boolean: - case LiteralType::Empty: - default: - return {}; - } -} - -NullableSharedPtr Literal::operator*(const Literal& Other) const noexcept -{ - MatchOperandType(Type, Other.Type); - switch (Type) - { - case LiteralType::UnsignedByte: - return std::make_shared(Value.UnsignedByteValue * Other.Value.UnsignedByteValue); - case LiteralType::UnsignedShort: - return std::make_shared(Value.UnsignedShortValue * Other.Value.UnsignedShortValue); - case LiteralType::UnsignedInt: - return std::make_shared(Value.UnsignedIntValue * Other.Value.UnsignedIntValue); - case LiteralType::UnsignedLong: - return std::make_shared(Value.UnsignedLongValue * Other.Value.UnsignedLongValue); - case LiteralType::SignedByte: - return std::make_shared(Value.SignedByteValue * Other.Value.SignedByteValue); - case LiteralType::SignedShort: - return std::make_shared(Value.SignedShortValue * Other.Value.SignedShortValue); - case LiteralType::SignedInt: - return std::make_shared(Value.SignedIntValue * Other.Value.SignedIntValue); - case LiteralType::SignedLong: - return std::make_shared(Value.SignedLongValue * Other.Value.SignedLongValue); - case LiteralType::Double: - return std::make_shared(Value.DoubleValue * Other.Value.DoubleValue); - case LiteralType::Float: - return std::make_shared(Value.FloatValue * Other.Value.FloatValue); - - case LiteralType::String: - case LiteralType::Character: - case LiteralType::Boolean: - case LiteralType::Empty: - default: - return {}; - } -} - -NullableSharedPtr Literal::operator/(const Literal& Other) const noexcept -{ - MatchOperandType(Type, Other.Type); - switch (Type) - { - case LiteralType::UnsignedByte: - return std::make_shared(Value.UnsignedByteValue / Other.Value.UnsignedByteValue); - case LiteralType::UnsignedShort: - return std::make_shared(Value.UnsignedShortValue / Other.Value.UnsignedShortValue); - case LiteralType::UnsignedInt: - return std::make_shared(Value.UnsignedIntValue / Other.Value.UnsignedIntValue); - case LiteralType::UnsignedLong: - return std::make_shared(Value.UnsignedLongValue / Other.Value.UnsignedLongValue); - case LiteralType::SignedByte: - return std::make_shared(Value.SignedByteValue / Other.Value.SignedByteValue); - case LiteralType::SignedShort: - return std::make_shared(Value.SignedShortValue / Other.Value.SignedShortValue); - case LiteralType::SignedInt: - return std::make_shared(Value.SignedIntValue / Other.Value.SignedIntValue); - case LiteralType::SignedLong: - return std::make_shared(Value.SignedLongValue / Other.Value.SignedLongValue); - case LiteralType::Double: - return std::make_shared(Value.DoubleValue / Other.Value.DoubleValue); - case LiteralType::Float: - return std::make_shared(Value.FloatValue / Other.Value.FloatValue); - - case LiteralType::Boolean: - case LiteralType::Empty: - case LiteralType::String: - case LiteralType::Character: - default: - return {}; - } -} - -NullableSharedPtr Literal::operator&(const Literal& Other) const noexcept -{ - MatchOperandType(Type, Other.Type); - switch (Type) - { - case LiteralType::UnsignedByte: - return std::make_shared(Value.UnsignedByteValue & Other.Value.UnsignedByteValue); - case LiteralType::UnsignedShort: - return std::make_shared(Value.UnsignedShortValue & Other.Value.UnsignedShortValue); - case LiteralType::UnsignedInt: - return std::make_shared(Value.UnsignedIntValue & Other.Value.UnsignedIntValue); - case LiteralType::UnsignedLong: - return std::make_shared(Value.UnsignedLongValue & Other.Value.UnsignedLongValue); - case LiteralType::SignedByte: - return std::make_shared(Value.SignedByteValue & Other.Value.SignedByteValue); - case LiteralType::SignedShort: - return std::make_shared(Value.SignedShortValue & Other.Value.SignedShortValue); - case LiteralType::SignedInt: - return std::make_shared(Value.SignedIntValue & Other.Value.SignedIntValue); - case LiteralType::SignedLong: - return std::make_shared(Value.SignedLongValue & Other.Value.SignedLongValue); - - case LiteralType::String: - case LiteralType::Character: - case LiteralType::Double: - case LiteralType::Float: - case LiteralType::Boolean: - case LiteralType::Empty: - default: - return {}; - } -} - -NullableSharedPtr Literal::operator|(const Literal& Other) const noexcept -{ - MatchOperandType(Type, Other.Type); - switch (Type) - { - case LiteralType::UnsignedByte: - return std::make_shared(Value.UnsignedByteValue | Other.Value.UnsignedByteValue); - case LiteralType::UnsignedShort: - return std::make_shared(Value.UnsignedShortValue | Other.Value.UnsignedShortValue); - case LiteralType::UnsignedInt: - return std::make_shared(Value.UnsignedIntValue | Other.Value.UnsignedIntValue); - case LiteralType::UnsignedLong: - return std::make_shared(Value.UnsignedLongValue | Other.Value.UnsignedLongValue); - case LiteralType::SignedByte: - return std::make_shared(Value.SignedByteValue | Other.Value.SignedByteValue); - case LiteralType::SignedShort: - return std::make_shared(Value.SignedShortValue | Other.Value.SignedShortValue); - case LiteralType::SignedInt: - return std::make_shared(Value.SignedIntValue | Other.Value.SignedIntValue); - case LiteralType::SignedLong: - return std::make_shared(Value.SignedLongValue | Other.Value.SignedLongValue); - case LiteralType::Boolean: - return std::make_shared(Value.BooleanValue | Other.Value.BooleanValue); - - case LiteralType::String: - case LiteralType::Character: - case LiteralType::Double: - case LiteralType::Float: - case LiteralType::Empty: - default: - return {}; - } -} - -NullableSharedPtr Literal::operator^(const Literal& Other) const noexcept -{ - MatchOperandType(Type, Other.Type); - switch (Type) - { - case LiteralType::UnsignedByte: - return std::make_shared(Value.UnsignedByteValue ^ Other.Value.UnsignedByteValue); - case LiteralType::UnsignedShort: - return std::make_shared(Value.UnsignedShortValue ^ Other.Value.UnsignedShortValue); - case LiteralType::UnsignedInt: - return std::make_shared(Value.UnsignedIntValue ^ Other.Value.UnsignedIntValue); - case LiteralType::UnsignedLong: - return std::make_shared(Value.UnsignedLongValue ^ Other.Value.UnsignedLongValue); - case LiteralType::SignedByte: - return std::make_shared(Value.SignedByteValue ^ Other.Value.SignedByteValue); - case LiteralType::SignedShort: - return std::make_shared(Value.SignedShortValue ^ Other.Value.SignedShortValue); - - case LiteralType::SignedInt: - return std::make_shared(Value.SignedIntValue ^ Other.Value.SignedIntValue); - case LiteralType::SignedLong: - return std::make_shared(Value.SignedLongValue ^ Other.Value.SignedLongValue); - - case LiteralType::String: - case LiteralType::Character: - case LiteralType::Double: - case LiteralType::Float: - case LiteralType::Boolean: - case LiteralType::Empty: - default: - return {}; - } -} - -NullableSharedPtr Literal::operator&&(const Literal& Other) const noexcept -{ - MatchOperandType(Type, Other.Type); - switch (Type) - { - case LiteralType::Boolean: - return std::make_shared(Value.BooleanValue && Other.Value.BooleanValue); - - case LiteralType::String: - case LiteralType::Character: - case LiteralType::UnsignedByte: - case LiteralType::UnsignedShort: - case LiteralType::UnsignedInt: - case LiteralType::UnsignedLong: - case LiteralType::SignedByte: - case LiteralType::SignedShort: - case LiteralType::SignedInt: - case LiteralType::SignedLong: - case LiteralType::Double: - case LiteralType::Float: - case LiteralType::Empty: - default: - return {}; - } -} - -NullableSharedPtr Literal::operator||(const Literal& Other) const noexcept -{ - MatchOperandType(Type, Other.Type); - switch (Type) - { - case LiteralType::Boolean: - return std::make_shared(Value.BooleanValue || Other.Value.BooleanValue); - - case LiteralType::String: - case LiteralType::Character: - case LiteralType::UnsignedByte: - case LiteralType::UnsignedShort: - case LiteralType::UnsignedInt: - case LiteralType::UnsignedLong: - case LiteralType::SignedByte: - case LiteralType::SignedShort: - case LiteralType::SignedInt: - case LiteralType::SignedLong: - case LiteralType::Double: - case LiteralType::Float: - case LiteralType::Empty: - default: - return {}; - } -} - -NullableSharedPtr Literal::operator==(const Literal& Other) const noexcept -{ - MatchOperandType(Type, Other.Type); - switch (Type) - { - case LiteralType::UnsignedByte: - return std::make_shared(Value.UnsignedByteValue == Other.Value.UnsignedByteValue); - case LiteralType::UnsignedShort: - return std::make_shared(Value.UnsignedShortValue == Other.Value.UnsignedShortValue); - case LiteralType::UnsignedInt: - return std::make_shared(Value.UnsignedIntValue == Other.Value.UnsignedIntValue); - case LiteralType::UnsignedLong: - return std::make_shared(Value.UnsignedLongValue == Other.Value.UnsignedLongValue); - case LiteralType::SignedByte: - return std::make_shared(Value.SignedByteValue == Other.Value.SignedByteValue); - case LiteralType::SignedShort: - return std::make_shared(Value.SignedShortValue == Other.Value.SignedShortValue); - case LiteralType::SignedInt: - return std::make_shared(Value.SignedIntValue == Other.Value.SignedIntValue); - case LiteralType::SignedLong: - return std::make_shared(Value.SignedLongValue == Other.Value.SignedLongValue); - case LiteralType::Double: - return std::make_shared(Value.DoubleValue == Other.Value.DoubleValue); - case LiteralType::Float: - return std::make_shared(Value.FloatValue == Other.Value.FloatValue); - case LiteralType::Boolean: - return std::make_shared(Value.BooleanValue == Other.Value.BooleanValue); - case LiteralType::String: - return std::make_shared(Value.StringValue == Other.Value.StringValue); - case LiteralType::Character: - return std::make_shared(Value.CharacterValue == Other.Value.CharacterValue); - case LiteralType::Empty: - default: - return {}; - } -} - -NullableSharedPtr Literal::operator!=(const Literal& Other) const noexcept -{ - MatchOperandType(Type, Other.Type); - switch (Type) - { - case LiteralType::String: - return std::make_shared(Value.StringValue != Other.Value.StringValue); - case LiteralType::Character: - return std::make_shared(Value.CharacterValue != Other.Value.CharacterValue); - case LiteralType::UnsignedByte: - return std::make_shared(Value.UnsignedByteValue != Other.Value.UnsignedByteValue); - case LiteralType::UnsignedShort: - return std::make_shared(Value.UnsignedShortValue != Other.Value.UnsignedShortValue); - case LiteralType::UnsignedInt: - return std::make_shared(Value.UnsignedIntValue != Other.Value.UnsignedIntValue); - case LiteralType::UnsignedLong: - return std::make_shared(Value.UnsignedLongValue != Other.Value.UnsignedLongValue); - case LiteralType::SignedByte: - return std::make_shared(Value.SignedByteValue != Other.Value.SignedByteValue); - case LiteralType::SignedShort: - return std::make_shared(Value.SignedShortValue != Other.Value.SignedShortValue); - case LiteralType::SignedInt: - return std::make_shared(Value.SignedIntValue != Other.Value.SignedIntValue); - case LiteralType::SignedLong: - return std::make_shared(Value.SignedLongValue != Other.Value.SignedLongValue); - case LiteralType::Double: - return std::make_shared(Value.DoubleValue != Other.Value.DoubleValue); - case LiteralType::Float: - return std::make_shared(Value.FloatValue != Other.Value.FloatValue); - case LiteralType::Boolean: - return std::make_shared(Value.BooleanValue != Other.Value.BooleanValue); - case LiteralType::Empty: - default: - return {}; - } -} - -NullableSharedPtr Literal::operator<(const Literal& Other) const noexcept -{ - MatchOperandType(Type, Other.Type); - switch (Type) - { - case LiteralType::UnsignedByte: - return std::make_shared(Value.UnsignedByteValue < Other.Value.UnsignedByteValue); - case LiteralType::UnsignedShort: - return std::make_shared(Value.UnsignedShortValue < Other.Value.UnsignedShortValue); - case LiteralType::UnsignedInt: - return std::make_shared(Value.UnsignedIntValue < Other.Value.UnsignedIntValue); - case LiteralType::UnsignedLong: - return std::make_shared(Value.UnsignedLongValue < Other.Value.UnsignedLongValue); - case LiteralType::SignedByte: - return std::make_shared(Value.SignedByteValue < Other.Value.SignedByteValue); - case LiteralType::SignedShort: - return std::make_shared(Value.SignedShortValue < Other.Value.SignedShortValue); - case LiteralType::SignedInt: - return std::make_shared(Value.SignedIntValue < Other.Value.SignedIntValue); - case LiteralType::SignedLong: - return std::make_shared(Value.SignedLongValue < Other.Value.SignedLongValue); - case LiteralType::Double: - return std::make_shared(Value.DoubleValue < Other.Value.DoubleValue); - case LiteralType::Float: - return std::make_shared(Value.FloatValue < Other.Value.FloatValue); - - case LiteralType::String: - case LiteralType::Character: - case LiteralType::Boolean: - case LiteralType::Empty: - default: - return {}; - } -} - -NullableSharedPtr Literal::operator<=(const Literal& Other) const noexcept -{ - MatchOperandType(Type, Other.Type); - switch (Type) - { - case LiteralType::UnsignedByte: - return std::make_shared(Value.UnsignedByteValue <= Other.Value.UnsignedByteValue); - case LiteralType::UnsignedShort: - return std::make_shared(Value.UnsignedShortValue <= Other.Value.UnsignedShortValue); - case LiteralType::UnsignedInt: - return std::make_shared(Value.UnsignedIntValue <= Other.Value.UnsignedIntValue); - case LiteralType::UnsignedLong: - return std::make_shared(Value.UnsignedLongValue <= Other.Value.UnsignedLongValue); - case LiteralType::SignedByte: - return std::make_shared(Value.SignedByteValue <= Other.Value.SignedByteValue); - case LiteralType::SignedShort: - return std::make_shared(Value.SignedShortValue <= Other.Value.SignedShortValue); - case LiteralType::SignedInt: - return std::make_shared(Value.SignedIntValue <= Other.Value.SignedIntValue); - case LiteralType::SignedLong: - return std::make_shared(Value.SignedLongValue <= Other.Value.SignedLongValue); - case LiteralType::Double: - return std::make_shared(Value.DoubleValue <= Other.Value.DoubleValue); - case LiteralType::Float: - return std::make_shared(Value.FloatValue <= Other.Value.FloatValue); - - case LiteralType::String: - case LiteralType::Character: - case LiteralType::Boolean: - case LiteralType::Empty: - default: - return {}; - } -} - -NullableSharedPtr Literal::operator>(const Literal& Other) const noexcept -{ - switch (Type) - { - case LiteralType::UnsignedByte: - return std::make_shared(Value.UnsignedByteValue > Other.Value.UnsignedByteValue); - case LiteralType::UnsignedShort: - return std::make_shared(Value.UnsignedShortValue > Other.Value.UnsignedShortValue); - case LiteralType::UnsignedInt: - return std::make_shared(Value.UnsignedIntValue > Other.Value.UnsignedIntValue); - case LiteralType::UnsignedLong: - return std::make_shared(Value.UnsignedLongValue > Other.Value.UnsignedLongValue); - case LiteralType::SignedByte: - return std::make_shared(Value.SignedByteValue > Other.Value.SignedByteValue); - case LiteralType::SignedShort: - return std::make_shared(Value.SignedShortValue > Other.Value.SignedShortValue); - case LiteralType::SignedInt: - return std::make_shared(Value.SignedIntValue > Other.Value.SignedIntValue); - case LiteralType::SignedLong: - return std::make_shared(Value.SignedLongValue > Other.Value.SignedLongValue); - case LiteralType::Double: - return std::make_shared(Value.DoubleValue > Other.Value.DoubleValue); - case LiteralType::Float: - return std::make_shared(Value.FloatValue > Other.Value.FloatValue); - case LiteralType::String: - case LiteralType::Character: - case LiteralType::Boolean: - case LiteralType::Empty: - default: - return {}; - } -} - -NullableSharedPtr Literal::operator>=(const Literal& Other) const noexcept -{ - MatchOperandType(Type, Other.Type); - switch (Type) - { - case LiteralType::UnsignedByte: - return std::make_shared(Value.UnsignedByteValue >= Other.Value.UnsignedByteValue); - case LiteralType::UnsignedShort: - return std::make_shared(Value.UnsignedShortValue >= Other.Value.UnsignedShortValue); - case LiteralType::UnsignedInt: - return std::make_shared(Value.UnsignedIntValue >= Other.Value.UnsignedIntValue); - case LiteralType::UnsignedLong: - return std::make_shared(Value.UnsignedLongValue >= Other.Value.UnsignedLongValue); - case LiteralType::SignedByte: - return std::make_shared(Value.SignedByteValue >= Other.Value.SignedByteValue); - case LiteralType::SignedShort: - return std::make_shared(Value.SignedShortValue >= Other.Value.SignedShortValue); - case LiteralType::SignedInt: - return std::make_shared(Value.SignedIntValue >= Other.Value.SignedIntValue); - case LiteralType::SignedLong: - return std::make_shared(Value.SignedLongValue >= Other.Value.SignedLongValue); - case LiteralType::Double: - return std::make_shared(Value.DoubleValue >= Other.Value.DoubleValue); - case LiteralType::Float: - return std::make_shared(Value.FloatValue >= Other.Value.FloatValue); - - case LiteralType::String: - case LiteralType::Character: - case LiteralType::Boolean: - case LiteralType::Empty: - default: - return {}; - } -} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/Literal.h b/src/Mamba/Code Analysis/Syntax/Literal.h index a9b9ece..727f26e 100644 --- a/src/Mamba/Code Analysis/Syntax/Literal.h +++ b/src/Mamba/Code Analysis/Syntax/Literal.h @@ -1,122 +1,38 @@ #pragma once #include "MambaCore.h" - -#include -#include -#include +#include namespace Mamba { - union LiteralValue - { - StringView StringValue; - Char CharacterValue; - - std::uint8_t UnsignedByteValue; - std::uint16_t UnsignedShortValue; - std::uint32_t UnsignedIntValue; - std::uint64_t UnsignedLongValue; - - std::int8_t SignedByteValue; - std::int16_t SignedShortValue; - std::int32_t SignedIntValue; - std::int64_t SignedLongValue; - - double DoubleValue; - float FloatValue; - - bool BooleanValue; - - LiteralValue() noexcept; - LiteralValue(const StringView String) noexcept; - LiteralValue(const std::int8_t Integer) noexcept; - LiteralValue(const std::int16_t Integer) noexcept; - LiteralValue(const std::int32_t Integer) noexcept; - LiteralValue(const std::int64_t Integer) noexcept; - LiteralValue(const std::uint8_t Integer) noexcept; - LiteralValue(const std::uint16_t Integer) noexcept; - LiteralValue(const std::uint32_t Integer) noexcept; - LiteralValue(const std::uint64_t Integer) noexcept; - LiteralValue(const float Value) noexcept; - LiteralValue(const double Value) noexcept; - LiteralValue(const bool Value) noexcept; - - private: - // In general, for some types of literal such as strings, this type only stores a view of the value, and the - // value is generally stored in the objects that holds this object. To ensure the validity of the view, this - // object can only be copied when the object that holds this object is copied. - // - // For example, Literal has a StringValue member variable, then the StringValue of this type is its view. This - // object can be only copied if the Literal object is copied. - LiteralValue(const LiteralValue&) = default; - LiteralValue(LiteralValue&&) = default; - - friend struct Literal; - }; - - enum class LiteralType + struct LiteralType { - String, - Character, - - UnsignedByte, - UnsignedShort, - UnsignedInt, - UnsignedLong, - - SignedByte, - SignedShort, - SignedInt, - SignedLong, - - Double, - Float, - - Boolean, - - Empty + using String = StringView; + using FloatingPoint = double; + using Number = std::uint64_t; + using Boolean = bool; + using Empty = std::monostate; }; struct Literal { - LiteralValue Value; - LiteralType Type; + using ValueType = std::variant; - ::std::optional> StringValue; + ValueType Value; - [[nodiscard]] Literal() noexcept; - [[nodiscard]] Literal(const std::shared_ptr String) noexcept; - [[nodiscard]] Literal(const std::int8_t Integer) noexcept; - [[nodiscard]] Literal(const std::int32_t Integer) noexcept; - [[nodiscard]] Literal(const std::int64_t Integer) noexcept; - [[nodiscard]] Literal(const std::uint8_t Integer) noexcept; - [[nodiscard]] Literal(const std::uint16_t Integer) noexcept; - [[nodiscard]] Literal(const std::uint32_t Integer) noexcept; - [[nodiscard]] Literal(const std::uint64_t Integer) noexcept; - [[nodiscard]] Literal(const Char Character) noexcept; - [[nodiscard]] Literal(const float Value) noexcept; - [[nodiscard]] Literal(const double Value) noexcept; - [[nodiscard]] Literal(const bool Value) noexcept; + [[nodiscard]] constexpr Literal() noexcept = default; - static NullableSharedPtr Negative(const Literal& Literal) noexcept; - static NullableSharedPtr LogicalNegative(const Literal& Literal) noexcept; - static NullableSharedPtr OnesComplement(const Literal& Literal) noexcept; + template + requires std::constructible_from + [[nodiscard]] constexpr Literal(T Value) noexcept : + Value(Value) + { + } - NullableSharedPtr operator+(const Literal& Other) const noexcept; - NullableSharedPtr operator-(const Literal& Other) const noexcept; - NullableSharedPtr operator*(const Literal& Other) const noexcept; - NullableSharedPtr operator/(const Literal& Other) const noexcept; - NullableSharedPtr operator&(const Literal& Other) const noexcept; - NullableSharedPtr operator|(const Literal& Other) const noexcept; - NullableSharedPtr operator^(const Literal& Other) const noexcept; - NullableSharedPtr operator&&(const Literal& Other) const noexcept; - NullableSharedPtr operator||(const Literal& Other) const noexcept; - NullableSharedPtr operator==(const Literal& Other) const noexcept; - NullableSharedPtr operator!=(const Literal& Other) const noexcept; - NullableSharedPtr operator<(const Literal& Other) const noexcept; - NullableSharedPtr operator<=(const Literal& Other) const noexcept; - NullableSharedPtr operator>(const Literal& Other) const noexcept; - NullableSharedPtr operator>=(const Literal& Other) const noexcept; + template + [[nodiscard]] constexpr T Get() const noexcept + { + return std::get(Value); + } }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/LiteralExpressionSyntax.cpp b/src/Mamba/Code Analysis/Syntax/LiteralExpressionSyntax.cpp index 10cf809..c6a939e 100644 --- a/src/Mamba/Code Analysis/Syntax/LiteralExpressionSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/LiteralExpressionSyntax.cpp @@ -1,35 +1,40 @@ #include "LiteralExpressionSyntax.h" -#include "Literal.h" -#include "SyntaxToken.h" -#include "SyntaxTree.h" +using namespace Mamba; -namespace Mamba +LiteralExpressionSyntax::LiteralExpressionSyntax( + const SyntaxTree* SyntaxTree, + const SyntaxToken* LiteralToken +) noexcept : + Super(SyntaxTree), LiteralToken(LiteralToken), Value(LiteralToken->Value()) { - LiteralExpressionSyntax::LiteralExpressionSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr LiteralToken - ) noexcept : - Super(SyntaxTree), LiteralToken(LiteralToken), Value(LiteralToken->Value) - { - } +} - LiteralExpressionSyntax::LiteralExpressionSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr LiteralToken, - const std::shared_ptr Value - ) noexcept : - Super(SyntaxTree), LiteralToken(LiteralToken), Value(Value) - { - } +LiteralExpressionSyntax::LiteralExpressionSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* LiteralToken, + Literal Value +) noexcept : + Super(SyntaxTree), LiteralToken(LiteralToken), Value(Value) +{ +} - SyntaxKind LiteralExpressionSyntax::Kind() const noexcept - { - return SyntaxKind::LiteralExpression; - } +SyntaxKind LiteralExpressionSyntax::Kind() const noexcept +{ + return SyntaxKind::LiteralExpression; +} + +std::size_t LiteralExpressionSyntax::ChildrenCount() const noexcept +{ + return 1; +} - std::vector> LiteralExpressionSyntax::Children() const noexcept +const SyntaxNode* LiteralExpressionSyntax::ChildAt(std::size_t Index) const noexcept +{ + if (Index != 0) { - return { LiteralToken }; + ReportChildrenAccessOutOfBounds(Index); } -} // namespace Mamba \ No newline at end of file + + return LiteralToken; +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/LiteralExpressionSyntax.h b/src/Mamba/Code Analysis/Syntax/LiteralExpressionSyntax.h index 5c75653..ec0df70 100644 --- a/src/Mamba/Code Analysis/Syntax/LiteralExpressionSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/LiteralExpressionSyntax.h @@ -1,35 +1,25 @@ #pragma once #include "ExpressionSyntax.h" - -#include +#include "SyntaxToken.h" namespace Mamba { - // A expression that represents a literal value, empty values are disallowed class LiteralExpressionSyntax : public ExpressionSyntax { public: using Super = ExpressionSyntax; - [[nodiscard]] LiteralExpressionSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr LiteralToken - ) noexcept; - - [[nodiscard]] LiteralExpressionSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr LiteralToken, - // use class in this elaborated-type-specifier is valid, but may cause linker error under Microsoft ABI - // https://eel.is/c++draft/dcl.dcl#dcl.type.elab-7 - // https://zh.cppreference.com/w/cpp/language/elaborated_type_specifier - const std::shared_ptr Value - ) noexcept; + [[nodiscard]] LiteralExpressionSyntax(const class SyntaxTree* SyntaxTree, const SyntaxToken* LiteralToken) noexcept; + [[nodiscard]] LiteralExpressionSyntax(const class SyntaxTree* SyntaxTree, const SyntaxToken* LiteralToken, Literal Value) noexcept; SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::shared_ptr LiteralToken; - const std::shared_ptr Value; + const SyntaxToken* LiteralToken; + Literal Value; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/MemberSyntax.cpp b/src/Mamba/Code Analysis/Syntax/MemberSyntax.cpp index caa0085..ad25249 100644 --- a/src/Mamba/Code Analysis/Syntax/MemberSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/MemberSyntax.cpp @@ -2,5 +2,6 @@ namespace Mamba { - MemberSyntax::MemberSyntax(const std::shared_ptr SyntaxTree) noexcept : Super(SyntaxTree) {} + MemberSyntax::MemberSyntax(const class SyntaxTree* SyntaxTree) noexcept : + Super(SyntaxTree) {} } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/MemberSyntax.h b/src/Mamba/Code Analysis/Syntax/MemberSyntax.h index b452034..ef52136 100644 --- a/src/Mamba/Code Analysis/Syntax/MemberSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/MemberSyntax.h @@ -2,8 +2,6 @@ #include "SyntaxNode.h" -#include - namespace Mamba { class MemberSyntax : public SyntaxNode @@ -12,6 +10,6 @@ namespace Mamba using Super = SyntaxNode; protected: - MemberSyntax(const std::shared_ptr SyntaxTree) noexcept; + MemberSyntax(const class SyntaxTree* SyntaxTree) noexcept; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/NameExpressionSyntax.cpp b/src/Mamba/Code Analysis/Syntax/NameExpressionSyntax.cpp index 1b800c8..2804e97 100644 --- a/src/Mamba/Code Analysis/Syntax/NameExpressionSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/NameExpressionSyntax.cpp @@ -1,22 +1,31 @@ #include "NameExpressionSyntax.h" -namespace Mamba +using namespace Mamba; + +NameExpressionSyntax::NameExpressionSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* IdentifierToken +) noexcept : + Super(SyntaxTree), IdentifierToken(IdentifierToken) { - NameExpressionSyntax::NameExpressionSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr IdentifierToken - ) noexcept : - Super(SyntaxTree), IdentifierToken(IdentifierToken) - { - } +} - SyntaxKind NameExpressionSyntax::Kind() const noexcept - { - return SyntaxKind::NameExpression; - } +SyntaxKind NameExpressionSyntax::Kind() const noexcept +{ + return SyntaxKind::NameExpression; +} + +std::size_t NameExpressionSyntax::ChildrenCount() const noexcept +{ + return 1; +} - std::vector> NameExpressionSyntax::Children() const noexcept +const SyntaxNode* NameExpressionSyntax::ChildAt(std::size_t Index) const noexcept +{ + if (Index != 0) { - return { IdentifierToken }; + ReportChildrenAccessOutOfBounds(Index); } -} // namespace Mamba \ No newline at end of file + + return IdentifierToken; +} diff --git a/src/Mamba/Code Analysis/Syntax/NameExpressionSyntax.h b/src/Mamba/Code Analysis/Syntax/NameExpressionSyntax.h index c4cc39f..3a6e730 100644 --- a/src/Mamba/Code Analysis/Syntax/NameExpressionSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/NameExpressionSyntax.h @@ -3,7 +3,6 @@ #include "ExpressionSyntax.h" #include "SyntaxToken.h" #include "SyntaxTree.h" -#include namespace Mamba { @@ -13,13 +12,16 @@ namespace Mamba using Super = ExpressionSyntax; [[nodiscard]] NameExpressionSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr IdentifierToken + const class SyntaxTree* SyntaxTree, + const SyntaxToken* IdentifierToken ) noexcept; SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::shared_ptr IdentifierToken; + const SyntaxToken* IdentifierToken; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/ParameterSyntax.cpp b/src/Mamba/Code Analysis/Syntax/ParameterSyntax.cpp index bbcef70..be7746e 100644 --- a/src/Mamba/Code Analysis/Syntax/ParameterSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/ParameterSyntax.cpp @@ -2,24 +2,41 @@ #include "TypeClauseSyntax.h" -namespace Mamba +using namespace Mamba; + +ParameterSyntax::ParameterSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* Identifier, + const TypeClauseSyntax* Type +) noexcept : + Super(SyntaxTree), Identifier(Identifier), Type(Type) { - ParameterSyntax::ParameterSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr Identifier, - const std::shared_ptr Type - ) noexcept : - Super(SyntaxTree), Identifier(Identifier), Type(Type) - { - } +} - SyntaxKind ParameterSyntax::Kind() const noexcept - { - return SyntaxKind::Parameter; - } +ParameterSyntax::~ParameterSyntax() noexcept +{ + delete Type; +} - std::vector> ParameterSyntax::Children() const noexcept +SyntaxKind ParameterSyntax::Kind() const noexcept +{ + return SyntaxKind::Parameter; +} + +std::size_t ParameterSyntax::ChildrenCount() const noexcept +{ + return 2; +} + +const SyntaxNode* ParameterSyntax::ChildAt(std::size_t Index) const noexcept +{ + switch (Index) { - return { Identifier, Type }; + case 0: + return Identifier; + case 1: + return Type; + default: + ReportChildrenAccessOutOfBounds(Index); } -} // namespace Mamba \ No newline at end of file +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/ParameterSyntax.h b/src/Mamba/Code Analysis/Syntax/ParameterSyntax.h index 81c15c1..0ef6217 100644 --- a/src/Mamba/Code Analysis/Syntax/ParameterSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/ParameterSyntax.h @@ -3,7 +3,7 @@ #include "SyntaxNode.h" #include "SyntaxToken.h" #include "SyntaxTree.h" -#include +#include "TypeClauseSyntax.h" namespace Mamba { @@ -13,15 +13,20 @@ namespace Mamba using Super = SyntaxNode; [[nodiscard]] ParameterSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr Identifier, - const std::shared_ptr Type + const class SyntaxTree* SyntaxTree, + const SyntaxToken* Identifier, + const TypeClauseSyntax* Type ) noexcept; + ~ParameterSyntax() noexcept override; + SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::shared_ptr Identifier; - const std::shared_ptr Type; + const SyntaxToken* Identifier; + const class TypeClauseSyntax* Type; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/ParenthesizedExpressionSyntax.cpp b/src/Mamba/Code Analysis/Syntax/ParenthesizedExpressionSyntax.cpp index 73bbfe5..3791158 100644 --- a/src/Mamba/Code Analysis/Syntax/ParenthesizedExpressionSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/ParenthesizedExpressionSyntax.cpp @@ -1,27 +1,46 @@ #include "ParenthesizedExpressionSyntax.h" -namespace Mamba +using namespace Mamba; + +ParenthesizedExpressionSyntax::ParenthesizedExpressionSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* OpenParenthesisToken, + const ExpressionSyntax* Expression, + const SyntaxToken* CloseParenthesisToken +) noexcept : + Super(SyntaxTree), + OpenParenthesisToken(OpenParenthesisToken), + Expression(Expression), + CloseParenthesisToken(CloseParenthesisToken) { - ParenthesizedExpressionSyntax::ParenthesizedExpressionSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr OpenParenthesisToken, - const std::shared_ptr Expression, - const std::shared_ptr CloseParenthesisToken - ) noexcept : - Super(SyntaxTree), - OpenParenthesisToken(OpenParenthesisToken), - Expression(Expression), - CloseParenthesisToken(CloseParenthesisToken) - { - } +} - SyntaxKind ParenthesizedExpressionSyntax::Kind() const noexcept - { - return SyntaxKind::ParenthesizedExpression; - } +ParenthesizedExpressionSyntax::~ParenthesizedExpressionSyntax() noexcept +{ + delete Expression; +} - std::vector> ParenthesizedExpressionSyntax::Children() const noexcept +SyntaxKind ParenthesizedExpressionSyntax::Kind() const noexcept +{ + return SyntaxKind::ParenthesizedExpression; +} + +std::size_t ParenthesizedExpressionSyntax::ChildrenCount() const noexcept +{ + return 3; +} + +const SyntaxNode* ParenthesizedExpressionSyntax::ChildAt(std::size_t Index) const noexcept +{ + switch (Index) { - return { OpenParenthesisToken, Expression, CloseParenthesisToken }; + case 0: + return OpenParenthesisToken; + case 1: + return Expression; + case 2: + return CloseParenthesisToken; + default: + ReportChildrenAccessOutOfBounds(Index); } -} // namespace Mamba \ No newline at end of file +} diff --git a/src/Mamba/Code Analysis/Syntax/ParenthesizedExpressionSyntax.h b/src/Mamba/Code Analysis/Syntax/ParenthesizedExpressionSyntax.h index 1b75e2a..ec967ec 100644 --- a/src/Mamba/Code Analysis/Syntax/ParenthesizedExpressionSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/ParenthesizedExpressionSyntax.h @@ -3,7 +3,6 @@ #include "ExpressionSyntax.h" #include "SyntaxToken.h" #include "SyntaxTree.h" -#include namespace Mamba { @@ -13,17 +12,22 @@ namespace Mamba using Super = ExpressionSyntax; [[nodiscard]] ParenthesizedExpressionSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr OpenParenthesisToken, - const std::shared_ptr Expression, - const std::shared_ptr CloseParenthesisToken + const class SyntaxTree* SyntaxTree, + const SyntaxToken* OpenParenthesisToken, + const ExpressionSyntax* Expression, + const SyntaxToken* CloseParenthesisToken ) noexcept; + ~ParenthesizedExpressionSyntax() noexcept override; + SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::shared_ptr OpenParenthesisToken; - const std::shared_ptr Expression; - const std::shared_ptr CloseParenthesisToken; + const SyntaxToken* OpenParenthesisToken; + const ExpressionSyntax* Expression; + const SyntaxToken* CloseParenthesisToken; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/Parser.cpp b/src/Mamba/Code Analysis/Syntax/Parser.cpp index 1a51e90..dba644b 100644 --- a/src/Mamba/Code Analysis/Syntax/Parser.cpp +++ b/src/Mamba/Code Analysis/Syntax/Parser.cpp @@ -1,591 +1,521 @@ #include "Parser.h" -#include - -#include "AssignmentExpressionSyntax.h" -#include "BinaryExpressionSyntax.h" -#include "BlockStatementSyntax.h" -#include "BreakStatementSyntax.h" -#include "CallExpressionSyntax.h" -#include "CompilationUnitSyntax.h" -#include "ContinueStatementSyntax.h" -#include "DoWhileStatementSyntax.h" -#include "ElseClauseSyntax.h" -#include "ExpressionStatementSyntax.h" -#include "ExpressionSyntax.h" -#include "fast_io.h" -#include "ForStatementSyntax.h" -#include "FunctionDeclarationSyntax.h" -#include "GlobalStatementSyntax.h" -#include "IfStatementSyntax.h" -#include "Lexer.h" -#include "Literal.h" -#include "LiteralExpressionSyntax.h" #include "MambaCore.h" -#include "NameExpressionSyntax.h" -#include "ParameterSyntax.h" -#include "ParenthesizedExpressionSyntax.h" -#include "ReturnStatementSyntax.h" -#include "StatementSyntax.h" #include "SyntaxFacts.h" -#include "SyntaxKind.h" -#include "SyntaxNode.h" -#include "SyntaxToken.h" #include "SyntaxTree.h" -#include "TypeClauseSyntax.h" #include "UnaryExpressionSyntax.h" -#include "VariableDeclarationSyntax.h" -#include "WhileStatementSyntax.h" -namespace Mamba +using namespace Mamba; + +Parser::Parser(const class SyntaxTree* SyntaxTree, std::vector&& Tokens) noexcept : + SyntaxTree(SyntaxTree), Tokens(std::move(Tokens)), Position(0) { - Parser::Parser(const std::shared_ptr SyntaxTree) noexcept : - SyntaxTree(SyntaxTree), Text(SyntaxTree->Text), Position() + if (this->Tokens.empty()) { - auto Lexer = ::Mamba::Lexer(SyntaxTree); - auto Token = std::shared_ptr(); - do - { - Token = Lexer.Lex(); - - if (Token->Kind() != SyntaxKind::BadToken && Token->Kind() != SyntaxKind::WhitespaceToken) - { - Tokens.emplace_back(Token); - } - } while (Token->Kind() != SyntaxKind::EndOfFileToken); - Diagnostics = std::move(Lexer.Diagnostics); + InternalCompilerError(std::source_location::current(), "No tokens provided to parser."); } - - std::shared_ptr Parser::Peek(const std::size_t Offset) noexcept + else if (this->Tokens.back().Kind() != SyntaxKind::EndOfFileToken) { - const auto Index = Position + Offset; - if (Index >= Tokens.size()) - { - return Tokens.back(); - } - - return Tokens[Index]; + InternalCompilerError(std::source_location::current(), "Tokens do not end with EndOfFileToken."); } +} - std::shared_ptr Parser::Current() noexcept - { - return Peek(0); - } +Parser::Parser(Parser&& Other) noexcept : + SyntaxTree(Other.SyntaxTree), + Tokens(std::move(Other.Tokens)), + Position(Other.Position) +{ + Other.SyntaxTree = {}; + Other.Position = 0; +} - std::shared_ptr Parser::NextToken() noexcept +const SyntaxToken* Parser::Peek(std::size_t Offset) noexcept +{ + auto Index = Position + Offset; + if (Index >= Tokens.size()) { - const auto Current = this->Current(); - ++Position; - return Current; + return &Tokens.back(); } - std::shared_ptr Parser::MatchToken(const SyntaxKind Kind) noexcept - { - if (Current()->Kind() == Kind) - { - return NextToken(); - } + return &Tokens[Index]; +} - Diagnostics.ReportUnexpectedToken(Current()->Location(), Current()->Kind(), Kind); - return std::make_shared( - SyntaxTree, - Kind, - Current()->Position, - std::make_shared(), - nullptr - ); - } +const SyntaxToken* Parser::Current() noexcept +{ + return Peek(0); +} + +const SyntaxToken* Parser::NextToken() noexcept +{ + const auto Current = this->Current(); + ++Position; + return Current; +} - std::shared_ptr Parser::ParseCompilationUnit() noexcept +const SyntaxToken* Parser::MatchToken(SyntaxKind Kind) noexcept +{ + if (Current()->Kind() == Kind) { - const auto Members = ParseMembers(); - const auto EndOfFileToken = MatchToken(SyntaxKind::EndOfFileToken); - return std::make_shared(SyntaxTree, std::move(Members), EndOfFileToken); + return NextToken(); } - std::vector> Parser::ParseMembers() noexcept - { - auto Members = std::vector>(); + Diagnostics.ReportUnexpectedToken(Current()->Location(), Current()->Kind(), Kind); + return Peek(1); +} - while (Current()->Kind() != SyntaxKind::EndOfFileToken) - { - const auto StartToken = Current(); - - const auto Member = ParseMember(); - Members.emplace_back(Member); - - // If ParseMember() did not consume any tokens, - // we need to skip the current token and continue - // in order to avoid an infinite loop. - // - // We don't need to report an error, because we'll - // already tried to parse an expression statement - // and reported one. - if (Current() == StartToken) - { - NextToken(); - } - } +CompilationUnitSyntax* Parser::ParseCompilationUnit() noexcept +{ + auto Members = ParseMembers(); + auto EndOfFileToken = MatchToken(SyntaxKind::EndOfFileToken); + return new CompilationUnitSyntax(SyntaxTree, std::move(Members), EndOfFileToken); +} - return Members; - } +std::vector Parser::ParseMembers() noexcept +{ + auto Members = std::vector(); - std::shared_ptr Parser::ParseMember() noexcept + while (Current()->Kind() != SyntaxKind::EndOfFileToken) { - if (Current()->Kind() == SyntaxKind::FunctionKeyword) - { - return ParseFunctionDeclaration(); - } - - return ParseGlobalStatement(); + auto Member = ParseMember(); + Members.emplace_back(Member); } - std::shared_ptr Parser::ParseFunctionDeclaration() noexcept - { - const auto FunctionKeyword = MatchToken(SyntaxKind::FunctionKeyword); - const auto IdentifierToken = MatchToken(SyntaxKind::IdentifierToken); - const auto OpenParenthesisToken = MatchToken(SyntaxKind::OpenParenthesisToken); - const auto Parameters = ParseParameterList(); - const auto CloseParenthesisToken = MatchToken(SyntaxKind::CloseParenthesisToken); - const auto Type = ParseOptionalTypeClause(); - const auto Body = ParseBlockStatement(); - - return std::make_shared( - SyntaxTree, - FunctionKeyword, - IdentifierToken, - OpenParenthesisToken, - Parameters, - CloseParenthesisToken, - Type, - Body - ); - } + return Members; +} - std::shared_ptr>> Parser::ParseParameterList() noexcept +MemberSyntax* Parser::ParseMember() noexcept +{ + auto StartToken = Current(); + auto Result = static_cast(nullptr); + if (Current()->Kind() == SyntaxKind::FunctionKeyword) { - auto NodesAndSeperators = std::vector>(); - - auto ParseNextParameter = true; - while (ParseNextParameter && Current()->Kind() != SyntaxKind::CloseParenthesisToken && Current()->Kind() != SyntaxKind::EndOfFileToken) - { - NodesAndSeperators.emplace_back( - Hatcher([&] - { return std::dynamic_pointer_cast(ParseParameter()); }) - ); - - if (Current()->Kind() == SyntaxKind::CommaToken) - { - NodesAndSeperators.emplace_back(Hatcher( - [&] - { return std::dynamic_pointer_cast(MatchToken(SyntaxKind::CommaToken)); } - )); - } - else - { - ParseNextParameter = false; - } - } - - return std::make_shared>>( - std::move(NodesAndSeperators) - ); + Result = ParseFunctionDeclaration(); } - - std::shared_ptr Parser::ParseParameter() noexcept + else { - const auto Identifier = MatchToken(SyntaxKind::IdentifierToken); - const auto Type = ParseTypeClause(); - return std::make_shared(SyntaxTree, Identifier, Type); + Result = ParseGlobalStatement(); } - std::shared_ptr Parser::ParseGlobalStatement() noexcept + if (Current() == StartToken) { - const auto Statement = ParseStatement(); - return std::make_shared(SyntaxTree, Statement); + NextToken(); } - std::shared_ptr Parser::ParseStatement() noexcept + return Result; +} + +FunctionDeclarationSyntax* Parser::ParseFunctionDeclaration() noexcept +{ + auto FunctionKeyword = MatchToken(SyntaxKind::FunctionKeyword); + auto IdentifierToken = MatchToken(SyntaxKind::IdentifierToken); + auto OpenParenthesisToken = MatchToken(SyntaxKind::OpenParenthesisToken); + auto Parameters = ParseParameterList(); + auto CloseParenthesisToken = MatchToken(SyntaxKind::CloseParenthesisToken); + auto Type = ParseOptionalTypeClause(); + auto Body = ParseBlockStatement(); + + return new FunctionDeclarationSyntax( + SyntaxTree, + FunctionKeyword, + IdentifierToken, + OpenParenthesisToken, + std::move(Parameters), + CloseParenthesisToken, + Type, + Body + ); +} + +SeperatedSyntaxList Parser::ParseParameterList() noexcept +{ + auto NodesAndSeperators = std::vector(); + + auto ParseNextParameter = true; + while (ParseNextParameter && + Current()->Kind() != SyntaxKind::CloseParenthesisToken && + Current()->Kind() != SyntaxKind::EndOfFileToken) { - switch (Current()->Kind()) + auto Parameter = ParseParameter(); + NodesAndSeperators.emplace_back(Parameter); + + if (Current()->Kind() == SyntaxKind::CommaToken) { - case SyntaxKind::OpenBraceToken: - return ParseBlockStatement(); - case SyntaxKind::LetKeyword: - case SyntaxKind::VarKeyword: - return ParseVariableDeclaration(); - case SyntaxKind::IfKeyword: - return ParseIfStatement(); - case SyntaxKind::WhileKeyword: - return ParseWhileStatement(); - case SyntaxKind::DoKeyword: - return ParseDoWhileStatement(); - case SyntaxKind::ForKeyword: - return ParseForStatement(); - case SyntaxKind::BreakKeyword: - return ParseBreakStatement(); - case SyntaxKind::ContinueKeyword: - return ParseContinueStatement(); - case SyntaxKind::ReturnKeyword: - return ParseReturnStatement(); - default: - return ParseExpressionStatement(); + auto Seperator = MatchToken(SyntaxKind::CommaToken); + NodesAndSeperators.emplace_back(Seperator); + } + else + { + ParseNextParameter = false; } } - std::shared_ptr Parser::ParseBlockStatement() noexcept - { - auto Statements = std::vector>(); + return SeperatedSyntaxList(std::move(NodesAndSeperators)); +} + +ParameterSyntax* Parser::ParseParameter() noexcept +{ + auto Identifier = MatchToken(SyntaxKind::IdentifierToken); + auto Type = ParseTypeClause(); + return new ParameterSyntax(SyntaxTree, Identifier, Type); +} - const auto OpenBraceToken = MatchToken(SyntaxKind::OpenBraceToken); +MemberSyntax* Parser::ParseGlobalStatement() noexcept +{ + const auto Statement = ParseStatement(); + return new GlobalStatementSyntax(SyntaxTree, Statement); +} - while (Current()->Kind() != SyntaxKind::EndOfFileToken && Current()->Kind() != SyntaxKind::CloseBraceToken) - { - const auto StartToken = Current(); - - Statements.emplace_back(Hatcher([&] - { return ParseStatement(); })); - - // If ParseStatement() did not consume any tokens, - // we need to skip the current token and continue - // in order to avoid an infinite loop. - // - // We don't need to report an error, because we'll - // already tried to parse an expression statement - // and reported one. - if (Current() == StartToken) - { - NextToken(); - } - } +StatementSyntax* Parser::ParseStatement() noexcept +{ + switch (Current()->Kind()) + { + case SyntaxKind::OpenBraceToken: + return ParseBlockStatement(); + case SyntaxKind::LetKeyword: + case SyntaxKind::VarKeyword: + return ParseVariableDeclaration(); + case SyntaxKind::IfKeyword: + return ParseIfStatement(); + case SyntaxKind::WhileKeyword: + return ParseWhileStatement(); + case SyntaxKind::DoKeyword: + return ParseDoWhileStatement(); + case SyntaxKind::ForKeyword: + return ParseForStatement(); + case SyntaxKind::BreakKeyword: + return ParseBreakStatement(); + case SyntaxKind::ContinueKeyword: + return ParseContinueStatement(); + case SyntaxKind::ReturnKeyword: + return ParseReturnStatement(); + default: + return ParseExpressionStatement(); + } +} + +BlockStatementSyntax* Parser::ParseBlockStatement() noexcept +{ + auto Statements = std::vector(); - const auto CloseBraceToken = MatchToken(SyntaxKind::CloseBraceToken); - return std::make_shared( - SyntaxTree, - OpenBraceToken, - std::move(Statements), - CloseBraceToken - ); - } + auto OpenBraceToken = MatchToken(SyntaxKind::OpenBraceToken); - std::shared_ptr Parser::ParseVariableDeclaration() noexcept + while (Current()->Kind() != SyntaxKind::EndOfFileToken && + Current()->Kind() != SyntaxKind::CloseBraceToken) { - const auto Expected = - Current()->Kind() == SyntaxKind::LetKeyword ? SyntaxKind::LetKeyword : SyntaxKind::VarKeyword; - const auto Keyword = MatchToken(Expected); - const auto Identifier = MatchToken(SyntaxKind::IdentifierToken); - const auto TypeClause = ParseOptionalTypeClause(); - const auto Equals = MatchToken(SyntaxKind::EqualsToken); - const auto Initializer = ParseExpression(); - return std::make_shared( - SyntaxTree, - Keyword, - Identifier, - TypeClause, - Equals, - Initializer - ); - } + auto StartToken = Current(); - NullableSharedPtr Parser::ParseOptionalTypeClause() noexcept - { - if (Current()->Kind() != SyntaxKind::ColonToken) + auto Statement = ParseStatement(); + Statements.emplace_back(Statement); + + // If ParseStatement() did not consume any tokens, + // we need to skip the current token and continue + // in order to avoid an infinite loop. + // + // We don't need to report an error, because we'll + // already tried to parse an expression statement + // and reported one. + if (Current() == StartToken) { - return nullptr; + NextToken(); } - - return ParseTypeClause(); } - std::shared_ptr Parser::ParseTypeClause() noexcept - { - const auto ColonToken = MatchToken(SyntaxKind::ColonToken); - const auto Identifier = MatchToken(SyntaxKind::IdentifierToken); - return std::make_shared(SyntaxTree, ColonToken, Identifier); - } + auto CloseBraceToken = MatchToken(SyntaxKind::CloseBraceToken); + return new BlockStatementSyntax(SyntaxTree, OpenBraceToken, std::move(Statements), CloseBraceToken); +} - std::shared_ptr Parser::ParseIfStatement() noexcept +VariableDeclarationSyntax* Parser::ParseVariableDeclaration() noexcept +{ + auto Expected = Current()->Kind() == SyntaxKind::LetKeyword ? SyntaxKind::LetKeyword : SyntaxKind::VarKeyword; + auto Keyword = MatchToken(Expected); + auto Identifier = MatchToken(SyntaxKind::IdentifierToken); + auto TypeClause = ParseOptionalTypeClause(); + auto Equals = MatchToken(SyntaxKind::EqualsToken); + auto Initializer = ParseExpression(); + return new VariableDeclarationSyntax(SyntaxTree, Keyword, Identifier, TypeClause, Equals, Initializer); +} + +NullablePointer Parser::ParseOptionalTypeClause() noexcept +{ + if (Current()->Kind() != SyntaxKind::ColonToken) { - const auto Keyword = MatchToken(SyntaxKind::IfKeyword); - const auto Condition = ParseExpression(); - const auto OpenParenthesisToken = Current()->Kind() == SyntaxKind::OpenParenthesisToken - ? MatchToken(SyntaxKind::OpenParenthesisToken) - : nullptr; - const auto Statement = ParseStatement(); - const auto CloseParenthesisToken = - OpenParenthesisToken ? MatchToken(SyntaxKind::CloseParenthesisToken) : nullptr; - const auto ElseClause = ParseOptionalElseClause(); - return std::make_shared( - SyntaxTree, - Keyword, - OpenParenthesisToken, - Condition, - CloseParenthesisToken, - Statement, - ElseClause - ); + return {}; } - NullableSharedPtr Parser::ParseOptionalElseClause() noexcept - { - if (Current()->Kind() != SyntaxKind::ElseKeyword) - { - return nullptr; - } + return ParseTypeClause(); +} - const auto Keyword = MatchToken(SyntaxKind::ElseKeyword); - const auto Statement = ParseStatement(); - return std::make_shared(SyntaxTree, Keyword, Statement); - } +TypeClauseSyntax* Parser::ParseTypeClause() noexcept +{ + auto ColonToken = MatchToken(SyntaxKind::ColonToken); + auto Identifier = MatchToken(SyntaxKind::IdentifierToken); + return new TypeClauseSyntax(SyntaxTree, ColonToken, Identifier); +} - std::shared_ptr Parser::ParseWhileStatement() noexcept +IfStatementSyntax* Parser::ParseIfStatement() noexcept +{ + auto Keyword = MatchToken(SyntaxKind::IfKeyword); + auto Condition = ParseExpression(); + auto Statement = ParseStatement(); + auto ElseClause = ParseOptionalElseClause(); + return new IfStatementSyntax(SyntaxTree, Keyword, Condition, Statement, ElseClause); +} + +NullablePointer Parser::ParseOptionalElseClause() noexcept +{ + if (Current()->Kind() != SyntaxKind::ElseKeyword) { - const auto Keyword = MatchToken(SyntaxKind::WhileKeyword); - const auto Condition = ParseExpression(); - const auto Body = ParseStatement(); - return std::make_shared(SyntaxTree, Keyword, Condition, Body); + return nullptr; } - std::shared_ptr Parser::ParseDoWhileStatement() noexcept - { - const auto DoKeyword = MatchToken(SyntaxKind::DoKeyword); - const auto Body = ParseStatement(); - const auto WhileKeyword = MatchToken(SyntaxKind::WhileKeyword); - const auto Condition = ParseExpression(); - return std::make_shared(SyntaxTree, DoKeyword, Body, WhileKeyword, Condition); - } + auto Keyword = MatchToken(SyntaxKind::ElseKeyword); + auto Statement = ParseStatement(); + return new ElseClauseSyntax(SyntaxTree, Keyword, Statement); +} - std::shared_ptr Parser::ParseForStatement() noexcept - { - const auto Keyword = MatchToken(SyntaxKind::ForKeyword); - const auto OpenParenthesisToken = MatchToken(SyntaxKind::OpenParenthesisToken); - const auto InitStatement = ParseStatement(); - const auto InitStatementColonToken = MatchToken(SyntaxKind::ColonToken); - const auto Condition = ParseExpression(); - const auto ConditionColonToken = MatchToken(SyntaxKind::ColonToken); - const auto Expression = ParseExpression(); - const auto CloseParenthesisToken = MatchToken(SyntaxKind::CloseParenthesisToken); - const auto Body = ParseStatement(); - return std::make_shared( - SyntaxTree, - Keyword, - OpenParenthesisToken, - InitStatement, - InitStatementColonToken, - Condition, - ConditionColonToken, - Expression, - CloseParenthesisToken, - Body - ); - } +WhileStatementSyntax* Parser::ParseWhileStatement() noexcept +{ + auto Keyword = MatchToken(SyntaxKind::WhileKeyword); + auto Condition = ParseExpression(); + auto Body = ParseStatement(); + return new WhileStatementSyntax(SyntaxTree, Keyword, Condition, Body); +} - std::shared_ptr Parser::ParseBreakStatement() noexcept - { - const auto Keyword = MatchToken(SyntaxKind::BreakKeyword); - return std::make_shared(SyntaxTree, Keyword); - } +DoWhileStatementSyntax* Parser::ParseDoWhileStatement() noexcept +{ + auto DoKeyword = MatchToken(SyntaxKind::DoKeyword); + auto Body = ParseStatement(); + auto WhileKeyword = MatchToken(SyntaxKind::WhileKeyword); + auto Condition = ParseExpression(); + return new DoWhileStatementSyntax(SyntaxTree, DoKeyword, Body, WhileKeyword, Condition); +} + +ForStatementSyntax* Parser::ParseForStatement() noexcept +{ + auto Keyword = MatchToken(SyntaxKind::ForKeyword); + auto OpenParenthesisToken = MatchToken(SyntaxKind::OpenParenthesisToken); + auto InitStatement = ParseStatement(); + auto InitStatementColonToken = MatchToken(SyntaxKind::ColonToken); + auto Condition = ParseExpression(); + auto ConditionColonToken = MatchToken(SyntaxKind::ColonToken); + auto Expression = ParseExpression(); + auto CloseParenthesisToken = MatchToken(SyntaxKind::CloseParenthesisToken); + auto Body = ParseStatement(); + return new ForStatementSyntax( + SyntaxTree, + Keyword, + OpenParenthesisToken, + InitStatement, + InitStatementColonToken, + Condition, + ConditionColonToken, + Expression, + CloseParenthesisToken, + Body + ); +} + +BreakStatementSyntax* Parser::ParseBreakStatement() noexcept +{ + auto Keyword = MatchToken(SyntaxKind::BreakKeyword); + return new BreakStatementSyntax(SyntaxTree, Keyword); +} - std::shared_ptr Parser::ParseContinueStatement() noexcept - { - const auto Keyword = MatchToken(SyntaxKind::ContinueKeyword); - return std::make_shared(SyntaxTree, Keyword); - } +ContinueStatementSyntax* Parser::ParseContinueStatement() noexcept +{ + auto Keyword = MatchToken(SyntaxKind::ContinueKeyword); + return new ContinueStatementSyntax(SyntaxTree, Keyword); +} - std::shared_ptr Parser::ParseReturnStatement() noexcept - { - const auto Keyword = MatchToken(SyntaxKind::ReturnKeyword); - const auto KeywordLine = Text->GetLineIndex(Keyword->Span().Start); - const auto CurrentLine = Text->GetLineIndex(Current()->Span().Start); - const auto IsEOF = Current()->Kind() == SyntaxKind::EndOfFileToken; - const auto SameLine = !IsEOF && KeywordLine == CurrentLine; - const auto Expression = SameLine ? ParseExpression() : nullptr; - return std::make_shared(SyntaxTree, Keyword, Expression); - } +ReturnStatementSyntax* Parser::ParseReturnStatement() noexcept +{ + auto Text = SyntaxTree->Text(); + + auto Keyword = MatchToken(SyntaxKind::ReturnKeyword); + auto KeywordLine = Text.LineIndex(Text.RelativeBegin(Keyword->Text())); + auto CurrentLine = Text.LineIndex(Text.RelativeBegin(Current()->Text())); + auto IsEOF = Current()->Kind() == SyntaxKind::EndOfFileToken; + auto SameLine = !IsEOF && KeywordLine == CurrentLine; + auto Expression = SameLine ? ParseExpression() : nullptr; + return new ReturnStatementSyntax(SyntaxTree, Keyword, Expression); +} + +ExpressionStatementSyntax* Parser::ParseExpressionStatement() noexcept +{ + auto Expression = ParseExpression(); + return new ExpressionStatementSyntax(SyntaxTree, Expression); +} - std::shared_ptr Parser::ParseExpressionStatement() noexcept - { - const auto Expression = ParseExpression(); - return std::make_shared(SyntaxTree, Expression); - } +ExpressionSyntax* Parser::ParseExpression() noexcept +{ + return ParseAssignmentExpression(); +} - std::shared_ptr Parser::ParseExpression() noexcept +ExpressionSyntax* Parser::ParseAssignmentExpression() noexcept +{ + if (Current()->Kind() != SyntaxKind::IdentifierToken) { - return ParseAssignmentExpression(); + return ParseBinaryExpression(); } - std::shared_ptr Parser::ParseAssignmentExpression() noexcept + switch (Peek(1)->Kind()) { - if (Current()->Kind() != SyntaxKind::IdentifierToken) + case SyntaxKind::PlusEqualsToken: + case SyntaxKind::MinusEqualsToken: + case SyntaxKind::StarEqualsToken: + case SyntaxKind::SlashEqualsToken: + case SyntaxKind::AmpersandEqualsToken: + case SyntaxKind::PipeEqualsToken: + case SyntaxKind::HatEqualsToken: + case SyntaxKind::EqualsToken: { - return ParseBinaryExpression(); + const auto IdentifierToken = NextToken(); + const auto OperatorToken = NextToken(); + const auto Right = ParseAssignmentExpression(); + return new AssignmentExpressionSyntax(SyntaxTree, IdentifierToken, OperatorToken, Right); } + default: + break; + } - switch (Peek(1)->Kind()) - { - case SyntaxKind::PlusEqualsToken: - case SyntaxKind::MinusEqualsToken: - case SyntaxKind::StarEqualsToken: - case SyntaxKind::SlashEqualsToken: - case SyntaxKind::AmpersandEqualsToken: - case SyntaxKind::PipeEqualsToken: - case SyntaxKind::HatEqualsToken: - case SyntaxKind::EqualsToken: - { - const auto IdentifierToken = NextToken(); - const auto OperatorToken = NextToken(); - const auto Right = ParseAssignmentExpression(); - return std::make_shared(SyntaxTree, IdentifierToken, OperatorToken, Right); - } - default: - break; - } + return ParseBinaryExpression(); +} - return ParseBinaryExpression(); +ExpressionSyntax* Parser::ParseUnaryOrPrimaryExpression(std::size_t ParentPrecedence) noexcept +{ + auto UnaryOperatorPrecedence = SyntaxFacts::GetUnaryOperatorPrecedence(Current()->Kind()); + if (UnaryOperatorPrecedence != 0 && UnaryOperatorPrecedence >= ParentPrecedence) + { + auto OperatorToken = NextToken(); + auto Operand = ParseBinaryExpression(UnaryOperatorPrecedence); + return new UnaryExpressionSyntax(SyntaxTree, OperatorToken, Operand); } - - std::shared_ptr Parser::ParseBinaryExpression(const std::size_t ParentPrecedence) noexcept + else { - auto Left = std::shared_ptr(); - const auto UnaryOperatorPrecedence = SyntaxFacts::GetUnaryOperatorPrecedence(Current()->Kind()); - if (UnaryOperatorPrecedence != 0 && UnaryOperatorPrecedence >= ParentPrecedence) - { - const auto OperatorToken = NextToken(); - const auto Operand = ParseBinaryExpression(UnaryOperatorPrecedence); - Left = std::make_shared(SyntaxTree, OperatorToken, Operand); - } - else - { - Left = ParsePrimaryExpression(); - } + return ParsePrimaryExpression(); + } +} - while (true) +ExpressionSyntax* Parser::ParseBinaryExpression(std::size_t ParentPrecedence) noexcept +{ + auto Left = ParseUnaryOrPrimaryExpression(); + while (true) + { + auto Precedence = SyntaxFacts::GetBinaryOperatorPrecedence(Current()->Kind()); + if (Precedence == 0 || Precedence <= ParentPrecedence) { - const auto Precedence = SyntaxFacts::GetBinaryOperatorPrecedence(Current()->Kind()); - if (Precedence == 0 || Precedence <= ParentPrecedence) - { - break; - } - - const auto OperatorToken = NextToken(); - const auto Right = ParseBinaryExpression(Precedence); - Left = std::make_shared(SyntaxTree, Left, OperatorToken, Right); + break; } - return Left; + auto OperatorToken = NextToken(); + auto Right = ParseBinaryExpression(Precedence); + Left = new BinaryExpressionSyntax(SyntaxTree, Left, OperatorToken, Right); } - std::shared_ptr Parser::ParsePrimaryExpression() noexcept + return Left; +} + +ExpressionSyntax* Parser::ParsePrimaryExpression() noexcept +{ + switch (Current()->Kind()) { - switch (Current()->Kind()) - { - case SyntaxKind::OpenParenthesisToken: - return ParseParenthesizedExpression(); + case SyntaxKind::OpenParenthesisToken: + return ParseParenthesizedExpression(); - case SyntaxKind::FalseKeyword: - case SyntaxKind::TrueKeyword: - return ParseBooleanLiteral(); + case SyntaxKind::FalseKeyword: + case SyntaxKind::TrueKeyword: + return ParseBooleanLiteral(); - case SyntaxKind::NumberToken: - return ParseNumericLiteral(); + case SyntaxKind::NumberToken: + return ParseNumericLiteral(); - case SyntaxKind::StringToken: - return ParseStringLiteral(); + case SyntaxKind::StringToken: + return ParseStringLiteral(); - case SyntaxKind::IdentifierToken: - default: - return ParseNameOrCallExpression(); - } + case SyntaxKind::IdentifierToken: + default: + return ParseNameOrCallExpression(); } +} - std::shared_ptr Parser::ParseParenthesizedExpression() noexcept - { - const auto Left = MatchToken(SyntaxKind::OpenParenthesisToken); - const auto Expression = ParseExpression(); - const auto Right = MatchToken(SyntaxKind::CloseParenthesisToken); - return std::make_shared(SyntaxTree, Left, Expression, Right); - } +ParenthesizedExpressionSyntax* Parser::ParseParenthesizedExpression() noexcept +{ + auto Left = MatchToken(SyntaxKind::OpenParenthesisToken); + auto Expression = ParseExpression(); + auto Right = MatchToken(SyntaxKind::CloseParenthesisToken); + return new ParenthesizedExpressionSyntax(SyntaxTree, Left, Expression, Right); +} - std::shared_ptr Parser::ParseBooleanLiteral() noexcept - { - const auto IsTrue = Current()->Kind() == SyntaxKind::TrueKeyword; - const auto KeywordToken = MatchToken(IsTrue ? SyntaxKind::TrueKeyword : SyntaxKind::FalseKeyword); - return std::make_shared( - SyntaxTree, - KeywordToken, - std::make_shared(IsTrue) - ); - } +LiteralExpressionSyntax* Parser::ParseBooleanLiteral() noexcept +{ + auto IsTrue = Current()->Kind() == SyntaxKind::TrueKeyword; + auto KeywordToken = MatchToken(IsTrue ? SyntaxKind::TrueKeyword : SyntaxKind::FalseKeyword); + return new LiteralExpressionSyntax(SyntaxTree, KeywordToken, IsTrue); +} - std::shared_ptr Parser::ParseNumericLiteral() noexcept - { - const auto NumberToken = MatchToken(SyntaxKind::NumberToken); - return std::make_shared(SyntaxTree, NumberToken); - } +LiteralExpressionSyntax* Parser::ParseNumericLiteral() noexcept +{ + auto NumberToken = MatchToken(SyntaxKind::NumberToken); + return new LiteralExpressionSyntax(SyntaxTree, NumberToken); +} - std::shared_ptr Parser::ParseStringLiteral() noexcept - { - const auto StringToken = MatchToken(SyntaxKind::StringToken); - return std::make_shared(SyntaxTree, StringToken); - } +LiteralExpressionSyntax* Parser::ParseStringLiteral() noexcept +{ + auto StringToken = MatchToken(SyntaxKind::StringToken); + return new LiteralExpressionSyntax(SyntaxTree, StringToken); +} - std::shared_ptr Parser::ParseNameOrCallExpression() noexcept +ExpressionSyntax* Parser::ParseNameOrCallExpression() noexcept +{ + if (Peek(0)->Kind() == SyntaxKind::IdentifierToken && Peek(1)->Kind() == SyntaxKind::OpenParenthesisToken) { - if (Peek(0)->Kind() == SyntaxKind::IdentifierToken && Peek(1)->Kind() == SyntaxKind::OpenParenthesisToken) - { - return ParseCallExpression(); - } - - return ParseNameExpression(); + return ParseCallExpression(); } - std::shared_ptr Parser::ParseCallExpression() noexcept - { - const auto Identifier = MatchToken(SyntaxKind::IdentifierToken); - const auto OpenParenthesisToken = MatchToken(SyntaxKind::OpenParenthesisToken); - const auto Arguments = ParseArguments(); - const auto CloseParenthesisToken = MatchToken(SyntaxKind::CloseParenthesisToken); - return std::make_shared( - SyntaxTree, - Identifier, - OpenParenthesisToken, - Arguments, - CloseParenthesisToken - ); - } + return ParseNameExpression(); +} + +CallExpressionSyntax* Parser::ParseCallExpression() noexcept +{ + auto Identifier = MatchToken(SyntaxKind::IdentifierToken); + auto OpenParenthesisToken = MatchToken(SyntaxKind::OpenParenthesisToken); + auto Arguments = ParseArguments(); + auto CloseParenthesisToken = MatchToken(SyntaxKind::CloseParenthesisToken); + return new CallExpressionSyntax( + SyntaxTree, + Identifier, + OpenParenthesisToken, + std::move(Arguments), + CloseParenthesisToken + ); +} + +SeperatedSyntaxList Parser::ParseArguments() noexcept +{ + auto NodesAndSeperators = std::vector(); - std::shared_ptr>> - Parser::ParseArguments() noexcept + auto ParseNextArgument = true; + while (ParseNextArgument && Current()->Kind() != SyntaxKind::CloseParenthesisToken && Current()->Kind() != SyntaxKind::EndOfFileToken) { - auto NodesAndSeperators = std::vector>(); + auto Expression = ParseExpression(); + NodesAndSeperators.emplace_back(Expression); - auto ParseNextArgument = true; - while (ParseNextArgument && Current()->Kind() != SyntaxKind::CloseParenthesisToken && Current()->Kind() != SyntaxKind::EndOfFileToken) + if (Current()->Kind() == SyntaxKind::CommaToken) { - NodesAndSeperators.emplace_back( - Hatcher([&] - { return std::dynamic_pointer_cast(ParseExpression()); }) - ); - - if (Current()->Kind() == SyntaxKind::CommaToken) - { - NodesAndSeperators.emplace_back(Hatcher( - [&] - { return std::dynamic_pointer_cast(MatchToken(SyntaxKind::CommaToken)); } - )); - } - else - { - ParseNextArgument = false; - } + auto Seperator = MatchToken(SyntaxKind::CommaToken); + NodesAndSeperators.emplace_back(Seperator); + } + else + { + ParseNextArgument = false; } - - return std::make_shared>>(std::move(NodesAndSeperators)); } - std::shared_ptr Parser::ParseNameExpression() noexcept - { - const auto IdentifierToken = MatchToken(SyntaxKind::IdentifierToken); - return std::make_shared(SyntaxTree, IdentifierToken); - } -} // namespace Mamba \ No newline at end of file + return SeperatedSyntaxList(std::move(NodesAndSeperators)); +} + +NameExpressionSyntax* Parser::ParseNameExpression() noexcept +{ + const auto IdentifierToken = MatchToken(SyntaxKind::IdentifierToken); + return new NameExpressionSyntax(SyntaxTree, IdentifierToken); +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/Parser.h b/src/Mamba/Code Analysis/Syntax/Parser.h index 3561cc4..46fb8ae 100644 --- a/src/Mamba/Code Analysis/Syntax/Parser.h +++ b/src/Mamba/Code Analysis/Syntax/Parser.h @@ -1,70 +1,89 @@ #pragma once -#include #include +#include "AssignmentExpressionSyntax.h" +#include "BinaryExpressionSyntax.h" +#include "BreakStatementSyntax.h" +#include "CallExpressionSyntax.h" +#include "CompilationUnitSyntax.h" +#include "ContinueStatementSyntax.h" #include "DiagnosticBag.h" +#include "DoWhileStatementSyntax.h" +#include "ElseClauseSyntax.h" +#include "ExpressionStatementSyntax.h" +#include "ForStatementSyntax.h" +#include "FunctionDeclarationSyntax.h" +#include "GlobalStatementSyntax.h" +#include "IfStatementSyntax.h" +#include "LiteralExpressionSyntax.h" +#include "NameExpressionSyntax.h" +#include "ParameterSyntax.h" +#include "ParenthesizedExpressionSyntax.h" +#include "ReturnStatementSyntax.h" #include "SeperatedSyntaxList.h" +#include "SyntaxToken.h" +#include "VariableDeclarationSyntax.h" +#include "WhileStatementSyntax.h" namespace Mamba { class Parser { - const std::shared_ptr SyntaxTree; - const std::shared_ptr Text; - std::vector> Tokens; + const class SyntaxTree* SyntaxTree; + std::vector Tokens; std::size_t Position; public: DiagnosticBag Diagnostics; - [[nodiscard]] Parser(const std::shared_ptr SyntaxTree) noexcept; + [[nodiscard]] Parser(const class SyntaxTree* SyntaxTree, std::vector&& Tokens) noexcept; + Parser(const Parser&) = delete; + Parser(Parser&& Other) noexcept; private: - [[nodiscard]] std::shared_ptr Peek(const std::size_t Offset) noexcept; - [[nodiscard]] std::shared_ptr Current() noexcept; - std::shared_ptr NextToken() noexcept; - [[nodiscard]] std::shared_ptr MatchToken(const SyntaxKind Kind) noexcept; + [[nodiscard]] const SyntaxToken* Peek(std::size_t Offset) noexcept; + [[nodiscard]] const SyntaxToken* Current() noexcept; + const SyntaxToken* NextToken() noexcept; + [[nodiscard]] const SyntaxToken* MatchToken(SyntaxKind Kind) noexcept; public: - [[nodiscard]] std::shared_ptr ParseCompilationUnit() noexcept; + [[nodiscard]] CompilationUnitSyntax* ParseCompilationUnit() noexcept; private: - [[nodiscard]] std::vector> ParseMembers() noexcept; - [[nodiscard]] std::shared_ptr ParseMember() noexcept; - [[nodiscard]] std::shared_ptr ParseFunctionDeclaration() noexcept; - [[nodiscard]] std::shared_ptr>> - ParseParameterList() noexcept; - [[nodiscard]] std::shared_ptr ParseParameter() noexcept; - [[nodiscard]] std::shared_ptr ParseGlobalStatement() noexcept; - [[nodiscard]] std::shared_ptr ParseStatement() noexcept; - [[nodiscard]] std::shared_ptr ParseBlockStatement() noexcept; - [[nodiscard]] std::shared_ptr ParseVariableDeclaration() noexcept; - [[nodiscard]] NullableSharedPtr ParseOptionalTypeClause() noexcept; - [[nodiscard]] std::shared_ptr ParseTypeClause() noexcept; - [[nodiscard]] std::shared_ptr ParseIfStatement() noexcept; - [[nodiscard]] NullableSharedPtr ParseOptionalElseClause() noexcept; - [[nodiscard]] std::shared_ptr ParseWhileStatement() noexcept; - [[nodiscard]] std::shared_ptr ParseDoWhileStatement() noexcept; - [[nodiscard]] std::shared_ptr ParseForStatement() noexcept; - [[nodiscard]] std::shared_ptr ParseBreakStatement() noexcept; - [[nodiscard]] std::shared_ptr ParseContinueStatement() noexcept; - [[nodiscard]] std::shared_ptr ParseReturnStatement() noexcept; - [[nodiscard]] std::shared_ptr ParseExpressionStatement() noexcept; - [[nodiscard]] std::shared_ptr ParseExpression() noexcept; - [[nodiscard]] std::shared_ptr ParseAssignmentExpression() noexcept; - [[nodiscard]] std::shared_ptr - ParseBinaryExpression(const std::size_t ParentPrecedence = 0) noexcept; - [[nodiscard]] std::shared_ptr ParsePrimaryExpression() noexcept; - [[nodiscard]] std::shared_ptr ParseParenthesizedExpression() noexcept; - [[nodiscard]] std::shared_ptr ParseBooleanLiteral() noexcept; - [[nodiscard]] std::shared_ptr ParseNumericLiteral() noexcept; - [[nodiscard]] std::shared_ptr ParseStringLiteral() noexcept; - [[nodiscard]] std::shared_ptr ParseNameOrCallExpression() noexcept; - [[nodiscard]] std::shared_ptr ParseCallExpression() noexcept; - [[nodiscard]] std::shared_ptr>> - ParseArguments() noexcept; - [[nodiscard]] std::shared_ptr ParseNameExpression() noexcept; + [[nodiscard]] ExpressionSyntax* ParseUnaryOrPrimaryExpression(std::size_t ParentPrecedence = 0) noexcept; + [[nodiscard]] ExpressionSyntax* ParseBinaryExpression(std::size_t ParentPrecedence = 0) noexcept; + [[nodiscard]] ParenthesizedExpressionSyntax* ParseParenthesizedExpression() noexcept; + [[nodiscard]] SeperatedSyntaxList ParseParameterList() noexcept; + [[nodiscard]] NullablePointer ParseOptionalTypeClause() noexcept; + [[nodiscard]] NullablePointer ParseOptionalElseClause() noexcept; + [[nodiscard]] SeperatedSyntaxList ParseArguments() noexcept; + [[nodiscard]] FunctionDeclarationSyntax* ParseFunctionDeclaration() noexcept; + [[nodiscard]] VariableDeclarationSyntax* ParseVariableDeclaration() noexcept; + [[nodiscard]] ExpressionStatementSyntax* ParseExpressionStatement() noexcept; + [[nodiscard]] ContinueStatementSyntax* ParseContinueStatement() noexcept; + [[nodiscard]] DoWhileStatementSyntax* ParseDoWhileStatement() noexcept; + [[nodiscard]] LiteralExpressionSyntax* ParseNumericLiteral() noexcept; + [[nodiscard]] LiteralExpressionSyntax* ParseBooleanLiteral() noexcept; + [[nodiscard]] ExpressionSyntax* ParseAssignmentExpression() noexcept; + [[nodiscard]] ExpressionSyntax* ParseNameOrCallExpression() noexcept; + [[nodiscard]] LiteralExpressionSyntax* ParseStringLiteral() noexcept; + [[nodiscard]] ReturnStatementSyntax* ParseReturnStatement() noexcept; + [[nodiscard]] CallExpressionSyntax* ParseCallExpression() noexcept; + [[nodiscard]] BlockStatementSyntax* ParseBlockStatement() noexcept; + [[nodiscard]] WhileStatementSyntax* ParseWhileStatement() noexcept; + [[nodiscard]] BreakStatementSyntax* ParseBreakStatement() noexcept; + [[nodiscard]] NameExpressionSyntax* ParseNameExpression() noexcept; + [[nodiscard]] ExpressionSyntax* ParsePrimaryExpression() noexcept; + [[nodiscard]] std::vector ParseMembers() noexcept; + [[nodiscard]] ForStatementSyntax* ParseForStatement() noexcept; + [[nodiscard]] IfStatementSyntax* ParseIfStatement() noexcept; + [[nodiscard]] MemberSyntax* ParseGlobalStatement() noexcept; + [[nodiscard]] ExpressionSyntax* ParseExpression() noexcept; + [[nodiscard]] TypeClauseSyntax* ParseTypeClause() noexcept; + [[nodiscard]] ParameterSyntax* ParseParameter() noexcept; + [[nodiscard]] StatementSyntax* ParseStatement() noexcept; + [[nodiscard]] MemberSyntax* ParseMember() noexcept; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/ReturnStatementSyntax.cpp b/src/Mamba/Code Analysis/Syntax/ReturnStatementSyntax.cpp index bbda6c6..118dc9a 100644 --- a/src/Mamba/Code Analysis/Syntax/ReturnStatementSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/ReturnStatementSyntax.cpp @@ -1,26 +1,40 @@ #include "ReturnStatementSyntax.h" -#include "ExpressionSyntax.h" -#include "SyntaxToken.h" +using namespace Mamba; -namespace Mamba +ReturnStatementSyntax::ReturnStatementSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* ReturnKeyword, + NullablePointer Expression +) noexcept : + Super(SyntaxTree), ReturnKeyword(ReturnKeyword), Expression(Expression) { - ReturnStatementSyntax::ReturnStatementSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr ReturnKeyword, - const NullableSharedPtr Expression - ) noexcept : - Super(SyntaxTree), ReturnKeyword(ReturnKeyword), Expression(Expression) - { - } +} - SyntaxKind ReturnStatementSyntax::Kind() const noexcept - { - return SyntaxKind::ReturnStatement; - } +ReturnStatementSyntax::~ReturnStatementSyntax() noexcept +{ + delete Expression; +} - std::vector> ReturnStatementSyntax::Children() const noexcept +SyntaxKind ReturnStatementSyntax::Kind() const noexcept +{ + return SyntaxKind::ReturnStatement; +} + +std::size_t ReturnStatementSyntax::ChildrenCount() const noexcept +{ + return 2; +} + +const SyntaxNode* ReturnStatementSyntax::ChildAt(std::size_t Index) const noexcept +{ + switch (Index) { - return { ReturnKeyword, Expression }; + case 0: + return ReturnKeyword; + case 1: + return Expression; + default: + ReportChildrenAccessOutOfBounds(Index); } -} // namespace Mamba \ No newline at end of file +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/ReturnStatementSyntax.h b/src/Mamba/Code Analysis/Syntax/ReturnStatementSyntax.h index c48f45b..56cdf53 100644 --- a/src/Mamba/Code Analysis/Syntax/ReturnStatementSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/ReturnStatementSyntax.h @@ -1,8 +1,8 @@ #pragma once +#include "ExpressionSyntax.h" #include "StatementSyntax.h" - -#include +#include "SyntaxToken.h" namespace Mamba { @@ -12,15 +12,20 @@ namespace Mamba using Super = StatementSyntax; [[nodiscard]] ReturnStatementSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr ReturnKeyword, - const NullableSharedPtr Expression + const class SyntaxTree* SyntaxTree, + const SyntaxToken* ReturnKeyword, + NullablePointer Expression ) noexcept; + ~ReturnStatementSyntax() noexcept override; + SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::shared_ptr ReturnKeyword; - const NullableSharedPtr Expression; + const SyntaxToken* ReturnKeyword; + NullablePointer Expression; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/SeperatedSyntaxList.h b/src/Mamba/Code Analysis/Syntax/SeperatedSyntaxList.h index 35c53f4..2688e95 100644 --- a/src/Mamba/Code Analysis/Syntax/SeperatedSyntaxList.h +++ b/src/Mamba/Code Analysis/Syntax/SeperatedSyntaxList.h @@ -1,50 +1,56 @@ #pragma once +#include #include #include #include +#include "SyntaxNode.h" + namespace Mamba { template typename Container = std::vector> - class SeperatedSyntaxList : Container + requires requires { + std::is_pointer_v; + std::derived_from::element_type, SyntaxNode>; + } + class SeperatedSyntaxList : public Container { - [[nodiscard]] constexpr Container SkipSeperators(const Container& NodesAndSeparators) const noexcept + [[nodiscard]] constexpr Container SkipSeperators(const Container& NodesAndSeparators) const noexcept { -#if __cpp_lib_ranges_enumerate == 202302L +#if __cpp_lib_ranges_enumerate >= 202302L // NodesAndSeparators | std::views::enumerate; #endif - if (NodesAndSeparators.size() == 1) { - return Container{ NodesAndSeparators.front() }; + return Container{ static_cast(NodesAndSeparators.front()) }; } auto Result = Container(NodesAndSeparators.size() / 2); -#if __cpp_size_t_suffix == 202011L +#if __cpp_size_t_suffix >= 202011L for (auto Index = 0uz; Index < NodesAndSeparators.size() / 2; ++Index) #else for (auto Index = std::size_t(); Index < NodesAndSeparators.size() / 2; ++Index) #endif { - Result[Index] = NodesAndSeparators[Index * 2]; + Result[Index] = static_cast(NodesAndSeparators[Index * 2]); } return Result; } public: - using Super = Container; + using Super = Container; + using ValueType = std::decay_t; - [[nodiscard]] constexpr SeperatedSyntaxList(Container&& NodesAndSeparators) noexcept : - Super(std::forward>(NodesAndSeparators)) + [[nodiscard]] constexpr SeperatedSyntaxList(Container&& NodesAndSeparators) noexcept : + Super(std::forward>(NodesAndSeparators)) { } template - [[nodiscard]] auto operator[](this SelfType&& Self, const std::size_t Index) - noexcept(noexcept(std::forward(Self).Super::operator[](Index)) - ) -> decltype(std::forward(Self).Super::operator[](Index)) + [[nodiscard]] auto operator[](this SelfType&& Self, std::size_t Index) + noexcept(noexcept(std::forward(Self).Super::operator[](Index))) { - return std::forward(Self).Super::operator[](Index * 2); + return static_cast(std::forward(Self).Super::operator[](Index * 2)); } [[nodiscard]] constexpr std::size_t Count() const noexcept @@ -57,19 +63,20 @@ namespace Mamba return SkipSeperators(*this); } + // TODO: use ranges instead [[nodiscard]] constexpr T GetSeparator(const std::size_t Index) const noexcept { return (*this)[Index * 2 + 1]; } - [[nodiscard]] constexpr const Container& WithSeperators() const noexcept + [[nodiscard]] constexpr const Container& WithSeperators() const noexcept { return *this; } template typename ToContainer> - [[nodiscard]] constexpr ToContainer WithSeperators() const noexcept + [[nodiscard]] constexpr ToContainer WithSeperators() const noexcept { return *this | std::ranges::to(); } diff --git a/src/Mamba/Code Analysis/Syntax/StatementSyntax.cpp b/src/Mamba/Code Analysis/Syntax/StatementSyntax.cpp index 8cd9509..411c942 100644 --- a/src/Mamba/Code Analysis/Syntax/StatementSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/StatementSyntax.cpp @@ -2,7 +2,7 @@ namespace Mamba { - StatementSyntax::StatementSyntax(const std::shared_ptr SyntaxTree) noexcept : + StatementSyntax::StatementSyntax(const class SyntaxTree* SyntaxTree) noexcept : Super(SyntaxTree) { } diff --git a/src/Mamba/Code Analysis/Syntax/StatementSyntax.h b/src/Mamba/Code Analysis/Syntax/StatementSyntax.h index eb28ab8..77ed32c 100644 --- a/src/Mamba/Code Analysis/Syntax/StatementSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/StatementSyntax.h @@ -2,8 +2,6 @@ #include "SyntaxNode.h" -#include - namespace Mamba { class StatementSyntax : public SyntaxNode @@ -12,6 +10,6 @@ namespace Mamba using Super = SyntaxNode; protected: - [[nodiscard]] StatementSyntax(const std::shared_ptr SyntaxTree) noexcept; + [[nodiscard]] StatementSyntax(const class SyntaxTree* SyntaxTree) noexcept; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/SyntaxFacts.cpp b/src/Mamba/Code Analysis/Syntax/SyntaxFacts.cpp index debf0e0..7e932fc 100644 --- a/src/Mamba/Code Analysis/Syntax/SyntaxFacts.cpp +++ b/src/Mamba/Code Analysis/Syntax/SyntaxFacts.cpp @@ -90,22 +90,36 @@ namespace Mamba std::vector SyntaxFacts::GetUnaryOperatorKinds() noexcept { - return { SyntaxKind::PlusToken, SyntaxKind::MinusToken, SyntaxKind::BangToken, SyntaxKind::TildeToken }; + return { + SyntaxKind::PlusToken, + SyntaxKind::MinusToken, + SyntaxKind::BangToken, + SyntaxKind::TildeToken + }; } std::vector SyntaxFacts::GetBinaryOperatorKinds() noexcept { - return { SyntaxKind::StarToken, SyntaxKind::SlashToken, - SyntaxKind::PlusToken, SyntaxKind::MinusToken, - SyntaxKind::EqualsEqualsToken, SyntaxKind::BangEqualsToken, - SyntaxKind::LessToken, SyntaxKind::LessOrEqualsToken, - SyntaxKind::GreaterToken, SyntaxKind::GreaterOrEqualsToken, - SyntaxKind::AmpersandToken, SyntaxKind::AmpersandAmpersandToken, - SyntaxKind::PipeToken, SyntaxKind::PipePipeToken, - SyntaxKind::HatToken }; + return { + SyntaxKind::StarToken, + SyntaxKind::SlashToken, + SyntaxKind::PlusToken, + SyntaxKind::MinusToken, + SyntaxKind::EqualsEqualsToken, + SyntaxKind::BangEqualsToken, + SyntaxKind::LessToken, + SyntaxKind::LessOrEqualsToken, + SyntaxKind::GreaterToken, + SyntaxKind::GreaterOrEqualsToken, + SyntaxKind::AmpersandToken, + SyntaxKind::AmpersandAmpersandToken, + SyntaxKind::PipeToken, + SyntaxKind::PipePipeToken, + SyntaxKind::HatToken + }; } - String SyntaxFacts::GetText(const SyntaxKind Kind) noexcept + StringView SyntaxFacts::GetText(const SyntaxKind Kind) noexcept { switch (Kind) { @@ -202,7 +216,7 @@ namespace Mamba } } - String SyntaxFacts::ToString(const SyntaxKind Kind) noexcept + StringView SyntaxFacts::ToString(const SyntaxKind Kind) noexcept { switch (Kind) { diff --git a/src/Mamba/Code Analysis/Syntax/SyntaxFacts.h b/src/Mamba/Code Analysis/Syntax/SyntaxFacts.h index bc0185d..13300d1 100644 --- a/src/Mamba/Code Analysis/Syntax/SyntaxFacts.h +++ b/src/Mamba/Code Analysis/Syntax/SyntaxFacts.h @@ -19,8 +19,8 @@ namespace Mamba [[nodiscard]] static SyntaxKind GetKeywordKind(const StringView Text) noexcept; [[nodiscard]] static std::vector GetUnaryOperatorKinds() noexcept; [[nodiscard]] static std::vector GetBinaryOperatorKinds() noexcept; - [[nodiscard]] static String GetText(const SyntaxKind Kind) noexcept; - [[nodiscard]] static String ToString(const SyntaxKind Kind) noexcept; + [[nodiscard]] static StringView GetText(const SyntaxKind Kind) noexcept; + [[nodiscard]] static StringView ToString(const SyntaxKind Kind) noexcept; [[nodiscard]] static bool IsKeyword(const SyntaxKind Kind) noexcept; [[nodiscard]] static bool IsToken(const SyntaxKind Kind) noexcept; [[nodiscard]] static SyntaxKind GetBinaryOperatorOfAssignmentOperator(const SyntaxKind Kind) noexcept; diff --git a/src/Mamba/Code Analysis/Syntax/SyntaxNode.cpp b/src/Mamba/Code Analysis/Syntax/SyntaxNode.cpp index 8adc967..3ba2071 100644 --- a/src/Mamba/Code Analysis/Syntax/SyntaxNode.cpp +++ b/src/Mamba/Code Analysis/Syntax/SyntaxNode.cpp @@ -1,203 +1,148 @@ #include "SyntaxNode.h" -#include "fast_io.h" -#include "Literal.h" -#include "MambaCore.h" -#include "SourceText.h" -#include "SyntaxFacts.h" -#include "SyntaxKind.h" #include "SyntaxToken.h" #include "SyntaxTree.h" -#include -#include -#include - -namespace Mamba -{ - SyntaxNode::SyntaxNode(const std::shared_ptr SyntaxTree) noexcept : - SyntaxTree(SyntaxTree) - { - } - - SyntaxNode::~SyntaxNode() noexcept {} - - const std::shared_ptr SyntaxNode::Parent() const noexcept - { - return SyntaxTree->GetParent(shared_from_this()); - } - - TextSpan SyntaxNode::Span() const noexcept - { - const auto First = Children().front()->Span(); - const auto Last = Children().back()->Span(); - return TextSpan::FromBounds(First.Start, Last.End()); - } - - TextSpan SyntaxNode::FullSpan() const noexcept - { - const auto First = Children().front()->FullSpan(); - const auto Last = Children().back()->FullSpan(); - return TextSpan::FromBounds(First.Start, Last.End()); - } - - TextLocation SyntaxNode::Location() const noexcept - { - return TextLocation(SyntaxTree->Text, Span()); - } - - std::vector> SyntaxNode::AncestorsAndSelf() const noexcept - { - auto Ancestors = std::vector>(); - auto Node = shared_from_this(); - while (Node) - { - Ancestors.emplace_back(Node); - Node = Node->Parent(); - } - - return Ancestors; - } - - std::vector> SyntaxNode::Ancestors() const noexcept - { - return AncestorsAndSelf() | std::views::drop(1) | std::ranges::to(); - } - - std::shared_ptr SyntaxNode::LastToken() const noexcept - { - if (auto Token = std::dynamic_pointer_cast(shared_from_this())) - { - return Token; - } - - // A syntax node should always contain at least 1 token. - return Children().back()->LastToken(); - } - - String SyntaxNode::ToString() const noexcept - { - auto Stream = std::basic_stringstream(); - PrettyPrint(Stream, shared_from_this()); - return Stream.str(); - } - - void SyntaxNode::PrettyPrint( - std::basic_stringstream& Stream, - const std::shared_ptr Node, - String Indent, - const bool IsLast - ) noexcept - { - const auto Token = std::dynamic_pointer_cast(Node); - const auto TokenMarker = String(IsLast ? TEXT("└──") : TEXT("├──")); - - Stream.write(Indent.data(), Indent.size()); - Stream.write(TokenMarker.data(), TokenMarker.size()); - - const auto KindText = SyntaxFacts::ToString(Node->Kind()); - Stream.write(KindText.data(), KindText.size()); - - if (Token && Token->Value) - { - Stream.put(TEXT(' ')); - switch (Token->Value->Type) - { - case LiteralType::String: - { - const auto String = *Token->Value->StringValue; - Stream.write(String->data(), String->size()); - break; - } - case LiteralType::Character: - Stream.put(Token->Value->Value.CharacterValue); - break; - case LiteralType::UnsignedByte: - { - const auto String = Concat(static_cast(Token->Value->Value.UnsignedByteValue)); - Stream.write(String.data(), String.size()); - break; - } - case LiteralType::UnsignedShort: - { - const auto String = Concat(Token->Value->Value.UnsignedShortValue); - Stream.write(String.data(), String.size()); - break; - } - case LiteralType::UnsignedInt: - { - const auto String = Concat(Token->Value->Value.UnsignedIntValue); - Stream.write(String.data(), String.size()); - break; - } - case LiteralType::UnsignedLong: - { - const auto String = Concat(Token->Value->Value.UnsignedLongValue); - Stream.write(String.data(), String.size()); - break; - } - case LiteralType::SignedByte: - { - const auto String = Concat(static_cast(Token->Value->Value.SignedByteValue)); - Stream.write(String.data(), String.size()); - break; - } - case LiteralType::SignedShort: - { - const auto String = Concat(Token->Value->Value.SignedShortValue); - Stream.write(String.data(), String.size()); - break; - } - case LiteralType::SignedInt: - { - const auto String = Concat(Token->Value->Value.SignedIntValue); - Stream.write(String.data(), String.size()); - break; - } - case LiteralType::SignedLong: - { - const auto String = Concat(Token->Value->Value.SignedLongValue); - Stream.write(String.data(), String.size()); - break; - } - case LiteralType::Double: - { - const auto String = Concat(Token->Value->Value.DoubleValue); - Stream.write(String.data(), String.size()); - break; - } - case LiteralType::Float: - { - const auto String = Concat(Token->Value->Value.FloatValue); - Stream.write(String.data(), String.size()); - break; - } - case LiteralType::Boolean: - { - const auto String = Concat(Token->Value->Value.BooleanValue); - Stream.write(String.data(), String.size()); - break; - } - case LiteralType::Empty: - break; - } - } - - if (Node->Kind() == SyntaxKind::IdentifierToken) - { - Stream.put(TEXT(' ')); - const auto View = Node->SyntaxTree->Text->ToView(Node->Span()); - Stream.write(View.data(), View.size()); - } - - Stream.put(TEXT('\n')); - - Indent += IsLast ? TEXT(" ") : TEXT("│ "); - - const auto LastChild = Node->Children().size() == 0 ? nullptr : Node->Children().back(); - - for (auto Child : Node->Children()) - { - PrettyPrint(Stream, Child, Indent, Child == LastChild); - } - } -} // namespace Mamba \ No newline at end of file + +using namespace Mamba; + +SyntaxNode::SyntaxNode(const class SyntaxTree* SyntaxTree) noexcept : + PrivateSyntaxTree(SyntaxTree) +{ +} + +NullablePointer SyntaxNode::Parent() const noexcept +{ + return Tree()->Parent(*this); +} + +const SyntaxTree* Mamba::SyntaxNode::Tree() const noexcept +{ + return PrivateSyntaxTree; +} + +StringView SyntaxNode::Text() const noexcept +{ + const auto First = Children().front()->Text(); + const auto Last = Children().back()->Text(); + return { First.begin(), Last.end() }; +} + +TextLocation SyntaxNode::Location() const noexcept +{ + return TextLocation{ + .Text = Tree()->Text(), + .View = Text(), + }; +} + +std::ranges::subrange SyntaxNode::Children() const noexcept +{ + auto Begin = ChildIterator{ this, 0 }; + auto End = ChildIterator{ this, ChildrenCount() }; + return std::ranges::subrange(Begin, End); +} + +std::ranges::subrange SyntaxNode::AncestorsAndSelf() const noexcept +{ + return std::ranges::subrange(AncestorsIterator(this), AncestorsIterator()); +} + +std::ranges::subrange SyntaxNode::Ancestors() const noexcept +{ + return AncestorsAndSelf() | std::views::drop(1); +} + +void SyntaxNode::ReportChildrenAccessOutOfBounds(std::size_t Index, std::source_location Location) noexcept +{ + InternalCompilerError(Location, "Children access out of bounds: ", Index); +} + +SyntaxNode::AncestorsIterator& SyntaxNode::AncestorsIterator::operator++() noexcept +{ + Current = Current->Parent(); + return *this; +} + +SyntaxNode::AncestorsIterator SyntaxNode::AncestorsIterator::operator++(int) noexcept +{ + auto Temp = *this; + ++*this; + return Temp; +} + +const SyntaxNode* SyntaxNode::AncestorsIterator::operator*() const +{ + return Current; +} + +SyntaxNode::ChildIterator& SyntaxNode::ChildIterator::operator++() noexcept +{ + ++Index; + return *this; +} + +SyntaxNode::ChildIterator SyntaxNode::ChildIterator::operator++(int) noexcept +{ + auto Temp = *this; + ++*this; + return Temp; +} + +SyntaxNode::ChildIterator& SyntaxNode::ChildIterator::operator+=(difference_type Offset) noexcept +{ + Index += Offset; + return *this; +} + +SyntaxNode::ChildIterator SyntaxNode::ChildIterator::operator+(const ChildIterator& Other) const noexcept +{ + auto Temp = *this; + Temp += Other.Index; + return Temp; +} + +SyntaxNode::ChildIterator& SyntaxNode::ChildIterator::operator--() noexcept +{ + --Index; + return *this; +} + +SyntaxNode::ChildIterator SyntaxNode::ChildIterator::operator--(int) noexcept +{ + auto Temp = *this; + --*this; + return Temp; +} + +SyntaxNode::ChildIterator& SyntaxNode::ChildIterator::operator-=(difference_type Offset) noexcept +{ + Index -= Offset; + return *this; +} + +SyntaxNode::ChildIterator SyntaxNode::ChildIterator::operator-(difference_type Offset) const noexcept +{ + auto Temp = *this; + Temp -= Offset; + return Temp; +} + +SyntaxNode::ChildIterator::difference_type SyntaxNode::ChildIterator::operator-(const ChildIterator& Other) const noexcept +{ + return Index - Other.Index; +} + +const SyntaxNode* SyntaxNode::ChildIterator::operator->() const noexcept +{ + return **this; +} + +const SyntaxNode* Mamba::SyntaxNode::ChildIterator::operator[](difference_type Index) const noexcept +{ + return Node->ChildAt(Index); +} + +const SyntaxNode* SyntaxNode::ChildIterator::operator*() const +{ + return Node->ChildAt(Index); +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/SyntaxNode.h b/src/Mamba/Code Analysis/Syntax/SyntaxNode.h index 4b929cd..503d93f 100644 --- a/src/Mamba/Code Analysis/Syntax/SyntaxNode.h +++ b/src/Mamba/Code Analysis/Syntax/SyntaxNode.h @@ -2,57 +2,120 @@ #include "SyntaxKind.h" #include "TextLocation.h" -#include "TextSpan.h" -#include #include -#include +#include namespace Mamba { - class SyntaxNode : public std::enable_shared_from_this + class SyntaxTree; + + // SyntaxNode is the minimum meaingful unit in the compilation, represents a syntactic element in the source code. + class SyntaxNode { - protected: - [[nodiscard]] SyntaxNode(const std::shared_ptr SyntaxTree) noexcept; + const class SyntaxTree* PrivateSyntaxTree; public: - virtual ~SyntaxNode() noexcept; + struct AncestorsIterator + { + using difference_type = std::ptrdiff_t; + + const SyntaxNode* Current; + + AncestorsIterator& operator++() noexcept; + AncestorsIterator operator++(int) noexcept; + + const SyntaxNode* operator*() const; + + friend bool operator==(const AncestorsIterator& Left, const AncestorsIterator& Right) noexcept = default; + }; + + struct ChildIterator + { + using difference_type = std::ptrdiff_t; + using value_type = const SyntaxNode*; + + const SyntaxNode* Node; + std::size_t Index; + + ChildIterator& operator++() noexcept; + ChildIterator operator++(int) noexcept; + ChildIterator& operator+=(difference_type Offset) noexcept; + ChildIterator operator+(const ChildIterator& Other) const noexcept; + + ChildIterator& operator--() noexcept; + ChildIterator operator--(int) noexcept; + ChildIterator& operator-=(difference_type Offset) noexcept; + ChildIterator operator-(difference_type Offset) const noexcept; + + difference_type operator-(const ChildIterator& Other) const noexcept; + + friend std::partial_ordering operator<=>(const ChildIterator& Left, const ChildIterator& Right) noexcept + { + return Left.Index <=> Right.Index; + } - const std::shared_ptr SyntaxTree; + const SyntaxNode* operator->() const noexcept; + const SyntaxNode* operator[](difference_type Index) const noexcept; - [[nodiscard]] const NullableSharedPtr Parent() const noexcept; + const SyntaxNode* operator*() const; + friend bool operator==(const ChildIterator& Left, const ChildIterator& Right) noexcept = default; + + friend ChildIterator operator+(const ChildIterator& Left, difference_type Offset) noexcept + { + auto Temp = Left; + Temp += Offset; + return Temp; + } + + friend ChildIterator operator+(difference_type Offset, const ChildIterator& Right) noexcept + { + auto Temp = Right; + Temp += Offset; + return Temp; + } + }; + + [[nodiscard]] SyntaxNode(const class SyntaxTree* SyntaxTree) noexcept; + + virtual ~SyntaxNode() noexcept = default; + + [[nodiscard]] NullablePointer Parent() const noexcept; + + [[nodiscard]] const SyntaxTree* Tree() const noexcept; [[nodiscard]] virtual SyntaxKind Kind() const noexcept = 0; - [[nodiscard]] virtual TextSpan Span() const noexcept; - [[nodiscard]] virtual TextSpan FullSpan() const noexcept; + + // Gets the text of the node in the source code, containing the whole node, including all its children. + [[nodiscard]] virtual StringView Text() const noexcept; + + // Gets the text location of the node in the source code, starts from the first child's beginning and + // ends at the last child's end. [[nodiscard]] TextLocation Location() const noexcept; // Gets all children of the node, children are member variables of types that indirectly or directly derived // from SyntaxNode, when implementing, the result sequence of children should conform to the sequence in which // they were defined within the type. If the member variable is a container whose element type is, or directly // or indirectly derived from SyntaxNode, it should be expanded and inserted in its original sequence. - [[nodiscard]] virtual std::vector> Children() const noexcept = 0; - [[nodiscard]] std::vector> AncestorsAndSelf() const noexcept; - [[nodiscard]] std::vector> Ancestors() const noexcept; - -#if defined(__cpp_lib_ranges_to_container) && __cpp_lib_ranges_to_container >= 202202L - template typename ContainerType> - [[nodiscard]] auto Children() const noexcept - { - return Children() | std::ranges::to(); - } -#endif + [[nodiscard]] std::ranges::subrange Children() const noexcept; - [[nodiscard]] std::shared_ptr LastToken() const noexcept; + // Gets all the ancestors of the node, including the node itself, in the order of closest to farthest. + [[nodiscard]] std::ranges::subrange AncestorsAndSelf() const noexcept; - String ToString() const noexcept; + // Gets all the ancestors of the node, excluding the node itself, in the order of closest to farthest. + [[nodiscard]] std::ranges::subrange Ancestors() const noexcept; private: - static void PrettyPrint( - std::basic_stringstream& Stream, - const std::shared_ptr Node, - String Indent = TEXT(""), - const bool IsLast = true - ) noexcept; + [[nodiscard]] virtual std::size_t ChildrenCount() const noexcept = 0; + [[nodiscard]] virtual const SyntaxNode* ChildAt(std::size_t Index) const noexcept = 0; + + protected: + [[noreturn]] static void ReportChildrenAccessOutOfBounds(std::size_t Index, std::source_location Location = std::source_location::current()) noexcept; }; + + static_assert(std::input_or_output_iterator); + static_assert(std::forward_iterator); + static_assert(std::bidirectional_iterator); + static_assert(std::ranges::common_range>); + static_assert(std::random_access_iterator); } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/SyntaxToken.cpp b/src/Mamba/Code Analysis/Syntax/SyntaxToken.cpp index 98f0c9b..a379a44 100644 --- a/src/Mamba/Code Analysis/Syntax/SyntaxToken.cpp +++ b/src/Mamba/Code Analysis/Syntax/SyntaxToken.cpp @@ -1,39 +1,39 @@ #include "SyntaxToken.h" -#include "MambaCore.h" -#include "TextSpan.h" +#include "SyntaxTree.h" -namespace Mamba +using namespace Mamba; + +SyntaxToken::SyntaxToken(const SyntaxTree* SyntaxTree, SyntaxKind Kind, StringView Text, Literal Value) noexcept : + Super(SyntaxTree), PrivateText(Text), PrivateValue(Value), PrivateKind(Kind) +{ +} + +SyntaxKind SyntaxToken::Kind() const noexcept +{ + return PrivateKind; +} + +StringView SyntaxToken::Text() const noexcept +{ + return PrivateText; +} + +std::size_t SyntaxToken::ChildrenCount() const noexcept +{ + return 0; +} + +const SyntaxNode* SyntaxToken::ChildAt(std::size_t Index [[maybe_unused]]) const noexcept +{ + return {}; +} + +std::size_t SyntaxToken::Position() const noexcept +{ + return Tree()->Text().RelativeBegin(Text()); +} + +Literal SyntaxToken::Value() const noexcept { - SyntaxToken::SyntaxToken( - const std::shared_ptr SyntaxTree, - const SyntaxKind Kind, - const std::size_t Position, - const std::shared_ptr Text, - const NullableSharedPtr Value - ) noexcept : - Super(SyntaxTree), Position(Position), Text(Text), Value(Value), KindValue(Kind) - { - } - - SyntaxKind SyntaxToken::Kind() const noexcept - { - return KindValue; - } - - TextSpan SyntaxToken::Span() const noexcept - { - return TextSpan(Position, Text->length()); - } - - TextSpan SyntaxToken::FullSpan() const noexcept - { - const auto Start = Span().Start; - const auto End = Span().End(); - return TextSpan::FromBounds(Start, End); - } - - std::vector> SyntaxToken::Children() const noexcept - { - return {}; - } -} // namespace Mamba \ No newline at end of file + return PrivateValue; +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/SyntaxToken.h b/src/Mamba/Code Analysis/Syntax/SyntaxToken.h index f22775a..ec97f64 100644 --- a/src/Mamba/Code Analysis/Syntax/SyntaxToken.h +++ b/src/Mamba/Code Analysis/Syntax/SyntaxToken.h @@ -1,38 +1,33 @@ #pragma once +#include "fast_io.h" +#include "Literal.h" #include "MambaCore.h" #include "SyntaxKind.h" #include "SyntaxNode.h" -#include "TextSpan.h" -#include namespace Mamba { + class SyntaxTree; + class SyntaxToken : public SyntaxNode { - using Super = SyntaxNode; + StringView PrivateText; + Literal PrivateValue; + SyntaxKind PrivateKind; public: - [[nodiscard]] SyntaxToken( - const std::shared_ptr SyntaxTree, - const SyntaxKind Kind, - const std::size_t Position, - const std::shared_ptr Text, - const NullableSharedPtr Value - ) noexcept; - - virtual SyntaxKind Kind() const noexcept override; + using Super = SyntaxNode; - virtual TextSpan Span() const noexcept override; - virtual TextSpan FullSpan() const noexcept override; + [[nodiscard]] SyntaxToken(const class SyntaxTree* SyntaxTree, SyntaxKind Kind, StringView Text, Literal Value = {}) noexcept; - virtual std::vector> Children() const noexcept override; + virtual SyntaxKind Kind() const noexcept override; + virtual StringView Text() const noexcept override; - std::size_t Position; - const std::shared_ptr Text; - const NullableSharedPtr Value; + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; - private: - SyntaxKind KindValue; + [[nodiscard]] std::size_t Position() const noexcept; + [[nodiscard]] Literal Value() const noexcept; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/SyntaxTree.cpp b/src/Mamba/Code Analysis/Syntax/SyntaxTree.cpp index 020c943..b8b51d2 100644 --- a/src/Mamba/Code Analysis/Syntax/SyntaxTree.cpp +++ b/src/Mamba/Code Analysis/Syntax/SyntaxTree.cpp @@ -1,188 +1,41 @@ #include "SyntaxTree.h" -#include "CompilationUnitSyntax.h" -#include "Diagnostic.h" -#include "Lexer.h" -#include "MambaCore.h" -#include "Parser.h" -#include "SourceText.h" -#include "SyntaxKind.h" -#include "SyntaxNode.h" -#include "SyntaxToken.h" +using namespace Mamba; -#include -#include -#include -#include - -namespace Mamba +SyntaxTree::SyntaxTree(const SourceText& SourceText) noexcept : + PrivateSourceText(SourceText) { - [[nodiscard]] String ReadFile(const StringView FileName) noexcept - { - fast_io::native_file_loader NativeFileLoader{ FileName }; - return String(NativeFileLoader.begin(), NativeFileLoader.end()); - } - - SyntaxTree::SyntaxTree(const std::shared_ptr Text) noexcept : - Text(Text) {} - - void SyntaxTree::Parse( - const std::shared_ptr SyntaxTree, - std::shared_ptr& Root, - std::vector& Diagnostics - ) noexcept - { - Parser Parser(SyntaxTree); - Root = Parser.ParseCompilationUnit(); - Diagnostics = std::move(Parser.Diagnostics); - } - - const std::shared_ptr SyntaxTree::Root() const noexcept - { - return PrivateRoot; - } - - const std::vector& SyntaxTree::Diagnostics() const noexcept - { - return PrivateDiagnostics; - } +} - SyntaxTree SyntaxTree::Load(const std::shared_ptr FileName) noexcept - { - const auto Text = std::make_shared(Hatcher([&] - { return ReadFile(*FileName); })); - const auto SourceText = - std::make_shared(Hatcher([=] - { return SourceText::From(Text, FileName); })); - return Parse(SourceText); - } - - SyntaxTree SyntaxTree::Parse(const std::shared_ptr Text) noexcept - { - const auto SourceText = - std::make_shared(Hatcher([&] - { return SourceText::From(Text); })); - return Parse(SourceText); - } - - SyntaxTree SyntaxTree::Parse(const std::shared_ptr Text) noexcept - { - using SyntaxTreeType = const std::shared_ptr; - using RootType = std::shared_ptr&; - using DiagnosticsType = std::vector&; - - using ParseFunctionType = void (&)(SyntaxTreeType, RootType, DiagnosticsType) noexcept; - - return SyntaxTree(Text, static_cast(Parse)); - } - - std::vector> - SyntaxTree::ParseTokens(const std::shared_ptr Text, const bool IncludeEndOfFile) noexcept - { - const auto SourceText = - std::make_shared(Hatcher([&] - { return SourceText::From(Text); })); - return ParseTokens(SourceText, IncludeEndOfFile); - } - - std::vector> SyntaxTree::ParseTokens( - const std::shared_ptr Text, - const bool IncludeEndOfFile - ) noexcept - { - return ParseTokens(Text, {}, IncludeEndOfFile); - } - - std::vector> SyntaxTree::ParseTokens( - const std::shared_ptr Text, - NullablePointer> Diagnostics, - const bool IncludeEndOfFile - ) noexcept - { - const auto SourceText = - std::make_shared(Hatcher([&] - { return SourceText::From(Text); })); - return ParseTokens(SourceText, Diagnostics, IncludeEndOfFile); - } - - std::vector> SyntaxTree::ParseTokens( - const std::shared_ptr Text, - NullablePointer> Diagnostics, - const bool IncludeEndOfFile - ) noexcept - { - auto Tokens = std::vector>(); - - const auto ParseTokens = [&](const std::shared_ptr SyntaxTree, - std::shared_ptr& Root, - std::vector& Diagnostics) noexcept - { - Lexer Lexer(SyntaxTree); - while (true) - { - const auto Token = Lexer.Lex(); - - if (Token->Kind() != SyntaxKind::EndOfFileToken || IncludeEndOfFile) - { - Tokens.emplace_back(Token); - } - - if (Token->Kind() == SyntaxKind::EndOfFileToken) - { - Root = std::make_shared( - SyntaxTree, - std::vector>{}, - Token - ); - break; - } - } - - Diagnostics = std::move(Lexer.Diagnostics); - }; - - ::Mamba::SyntaxTree SyntaxTree(Text, ParseTokens); - if (Diagnostics) - { - using t1 = decltype(*Diagnostics); - using t2 = decltype(SyntaxTree.Diagnostics()); - - *Diagnostics = SyntaxTree.Diagnostics(); - } +SyntaxTree::SyntaxTree(SyntaxTree&& Other) noexcept : + PrivateRoot(Other.PrivateRoot), + PrivateSourceText(Other.PrivateSourceText), + ParentsMap(std::move(Other.ParentsMap)) +{ + Other.PrivateRoot = {}; +} - return Tokens; - } +SyntaxTree::~SyntaxTree() noexcept +{ + delete PrivateRoot; +} - NullableSharedPtr SyntaxTree::GetParent(const std::shared_ptr Node - ) const noexcept +NullablePointer SyntaxTree::Parent(const SyntaxNode& Node) const noexcept +{ + const auto Iterator = ParentsMap.find(&Node); + if (Iterator == ParentsMap.end()) { - static auto Mutex = std::mutex{}; - - const auto LockGuard = std::lock_guard(Mutex); - if (!Parents) - { - const auto Parents = CreateParentsMap(Root()); - } - - return Parents->at(Node); + return {}; } - SyntaxTree::ParentsMapType - SyntaxTree::CreateParentsMap(const std::shared_ptr Root) const noexcept - { - auto Result = ParentsMapType(); - Result.emplace(Root, nullptr); - CreateParentsMap(Result, Root); - return Result; - } + return Iterator->second; +} - void SyntaxTree::CreateParentsMap(ParentsMapType& Result, const std::shared_ptr Node) - const noexcept +void SyntaxTree::BuildParentsMap(const SyntaxNode& Node) noexcept +{ + for (auto&& Child : Node.Children()) { - for (auto&& Child : Node->Children()) - { - Result.emplace(Child, Node); - CreateParentsMap(Result, Child); - } + ParentsMap.emplace(Child, &Node); + BuildParentsMap(*Child); } -} // namespace Mamba +} diff --git a/src/Mamba/Code Analysis/Syntax/SyntaxTree.h b/src/Mamba/Code Analysis/Syntax/SyntaxTree.h index fbdf3d2..cb0fe18 100644 --- a/src/Mamba/Code Analysis/Syntax/SyntaxTree.h +++ b/src/Mamba/Code Analysis/Syntax/SyntaxTree.h @@ -1,90 +1,48 @@ #pragma once -#include "MambaCore.h" - -#include -#include #include -#include -#include + +#include "CompilationUnitSyntax.h" +#include "MambaCore.h" +#include "SourceText.h" namespace Mamba { - class Compilation; + class SourceText; - class SyntaxTree : std::enable_shared_from_this + class SyntaxTree { - friend Compilation; - using ParentsMapType = - std::unordered_map, NullableSharedPtr>; - - std::optional Parents; - - [[nodiscard]] SyntaxTree(const std::shared_ptr Text, auto&& Handler) noexcept - requires requires { - Handler( - shared_from_this(), - std::declval&>(), - std::declval&>() - ); - } - : - Text(Text) - { - Handler(std::make_shared(*this), PrivateRoot, PrivateDiagnostics); - } + CompilationUnitSyntax* PrivateRoot; + const SourceText& PrivateSourceText; - std::shared_ptr PrivateRoot; - std::vector PrivateDiagnostics; - - static void Parse( - const std::shared_ptr SyntaxTree, - std::shared_ptr& Root, - std::vector& Diagnostics - ) noexcept; + friend class Compiler; public: - [[nodiscard]] SyntaxTree(const std::shared_ptr Text) noexcept; - - const std::shared_ptr Text; - [[nodiscard]] const std::shared_ptr Root() const noexcept; - [[nodiscard]] const std::vector& Diagnostics() const noexcept; + [[nodiscard]] SyntaxTree(const class SourceText& SourceText) noexcept; - [[deprecated("No longer support contructing SyntaxTree from file directly.")]] [[nodiscard]] static SyntaxTree - Load(const std::shared_ptr FileName) noexcept; + SyntaxTree(const SyntaxTree&) noexcept = delete; + SyntaxTree(SyntaxTree&& Other) noexcept; - [[nodiscard]] static SyntaxTree Parse(const std::shared_ptr Text) noexcept; - [[nodiscard]] static SyntaxTree Parse(const std::shared_ptr Text) noexcept; + SyntaxTree& operator=(const SyntaxTree&) noexcept = delete; - [[nodiscard]] static std::vector> ParseTokens( - const std::shared_ptr Text, - const bool IncludeEndOfFile = false - ) noexcept; + ~SyntaxTree() noexcept; - [[nodiscard]] static std::vector> ParseTokens( - const std::shared_ptr Text, - NullablePointer> Diagnostics, - const bool IncludeEndOfFile = false - ) noexcept; + template + [[nodiscard]] auto&& Root(this SelfT&& Self) noexcept + { + return std::forward(Self).PrivateRoot; + } - [[nodiscard]] static std::vector> ParseTokens( - const std::shared_ptr Text, - const bool IncludeEndOfFile = false - ) noexcept; - [[nodiscard]] static std::vector> ParseTokens( - const std::shared_ptr Text, - NullablePointer> Diagnostics, - const bool IncludeEndOfFile = false - ) noexcept; + template + [[nodiscard]] const SourceText& Text(this SelfT&& Self) noexcept + { + return std::forward(Self).PrivateSourceText; + } - [[nodiscard]] NullableSharedPtr - GetParent(const std::shared_ptr Node) const noexcept; + NullablePointer Parent(const SyntaxNode& Node) const noexcept; private: - [[nodiscard]] ParentsMapType CreateParentsMap(const std::shared_ptr Root - ) const noexcept; - - void - CreateParentsMap(ParentsMapType& Result, const std::shared_ptr Node) const noexcept; + void BuildParentsMap(const SyntaxNode& Root) noexcept; + std::unordered_map> ParentsMap; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/TypeClauseSyntax.cpp b/src/Mamba/Code Analysis/Syntax/TypeClauseSyntax.cpp index 8228eab..1e9d7b0 100644 --- a/src/Mamba/Code Analysis/Syntax/TypeClauseSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/TypeClauseSyntax.cpp @@ -2,24 +2,36 @@ #include "SyntaxToken.h" -namespace Mamba +using namespace Mamba; + +TypeClauseSyntax::TypeClauseSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* ColonToken, + const SyntaxToken* Identifier +) noexcept : + Super(SyntaxTree), ColonToken(ColonToken), Identifier(Identifier) { - TypeClauseSyntax::TypeClauseSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr ColonToken, - const std::shared_ptr Identifier - ) noexcept : - Super(SyntaxTree), ColonToken(ColonToken), Identifier(Identifier) - { - } +} - SyntaxKind TypeClauseSyntax::Kind() const noexcept - { - return SyntaxKind::TypeClause; - } +SyntaxKind TypeClauseSyntax::Kind() const noexcept +{ + return SyntaxKind::TypeClause; +} + +std::size_t TypeClauseSyntax::ChildrenCount() const noexcept +{ + return 2; +} - std::vector> TypeClauseSyntax::Children() const noexcept +const SyntaxNode* TypeClauseSyntax::ChildAt(std::size_t Index) const noexcept +{ + switch (Index) { - return { ColonToken, Identifier }; + case 0: + return ColonToken; + case 1: + return Identifier; + default: + ReportChildrenAccessOutOfBounds(Index); } -} // namespace Mamba \ No newline at end of file +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/TypeClauseSyntax.h b/src/Mamba/Code Analysis/Syntax/TypeClauseSyntax.h index cfe09a7..04b2bc4 100644 --- a/src/Mamba/Code Analysis/Syntax/TypeClauseSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/TypeClauseSyntax.h @@ -1,8 +1,7 @@ #pragma once #include "SyntaxNode.h" - -#include +#include "SyntaxToken.h" namespace Mamba { @@ -12,15 +11,18 @@ namespace Mamba using Super = SyntaxNode; [[nodiscard]] TypeClauseSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr ColonToken, - const std::shared_ptr Identifier + const class SyntaxTree* SyntaxTree, + const SyntaxToken* ColonToken, + const SyntaxToken* Identifier ) noexcept; SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::shared_ptr ColonToken; - const std::shared_ptr Identifier; + const SyntaxToken* ColonToken; + const SyntaxToken* Identifier; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/UnaryExpressionSyntax.cpp b/src/Mamba/Code Analysis/Syntax/UnaryExpressionSyntax.cpp index a1dcb57..fbee1cf 100644 --- a/src/Mamba/Code Analysis/Syntax/UnaryExpressionSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/UnaryExpressionSyntax.cpp @@ -1,23 +1,40 @@ #include "UnaryExpressionSyntax.h" -namespace Mamba +using namespace Mamba; + +UnaryExpressionSyntax::UnaryExpressionSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* OperatorToken, + const ExpressionSyntax* Operand +) noexcept : + Super(SyntaxTree), OperatorToken(OperatorToken), Operand(Operand) { - UnaryExpressionSyntax::UnaryExpressionSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr OperatorToken, - const std::shared_ptr Operand - ) noexcept : - Super(SyntaxTree), OperatorToken(OperatorToken), Operand(Operand) - { - } +} - SyntaxKind UnaryExpressionSyntax::Kind() const noexcept - { - return SyntaxKind::UnaryExpression; - } +UnaryExpressionSyntax::~UnaryExpressionSyntax() noexcept +{ + delete Operand; +} - std::vector> UnaryExpressionSyntax::Children() const noexcept +SyntaxKind UnaryExpressionSyntax::Kind() const noexcept +{ + return SyntaxKind::UnaryExpression; +} + +std::size_t UnaryExpressionSyntax::ChildrenCount() const noexcept +{ + return 2; +} + +const SyntaxNode* UnaryExpressionSyntax::ChildAt(std::size_t Index) const noexcept +{ + switch (Index) { - return { OperatorToken, Operand }; + case 0: + return OperatorToken; + case 1: + return Operand; + default: + ReportChildrenAccessOutOfBounds(Index); } -} // namespace Mamba \ No newline at end of file +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/UnaryExpressionSyntax.h b/src/Mamba/Code Analysis/Syntax/UnaryExpressionSyntax.h index 700b53f..cd9f83b 100644 --- a/src/Mamba/Code Analysis/Syntax/UnaryExpressionSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/UnaryExpressionSyntax.h @@ -3,7 +3,6 @@ #include "ExpressionSyntax.h" #include "SyntaxToken.h" #include "SyntaxTree.h" -#include namespace Mamba { @@ -13,15 +12,20 @@ namespace Mamba using Super = ExpressionSyntax; [[nodiscard]] UnaryExpressionSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr OperatorToken, - const std::shared_ptr Operand + const class SyntaxTree* SyntaxTree, + const SyntaxToken* OperatorToken, + const ExpressionSyntax* Operand ) noexcept; + ~UnaryExpressionSyntax() noexcept override; + SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::shared_ptr OperatorToken; - const std::shared_ptr Operand; + const SyntaxToken* OperatorToken; + const ExpressionSyntax* Operand; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/VariableDeclarationSyntax.cpp b/src/Mamba/Code Analysis/Syntax/VariableDeclarationSyntax.cpp index 1687be5..43e3b87 100644 --- a/src/Mamba/Code Analysis/Syntax/VariableDeclarationSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/VariableDeclarationSyntax.cpp @@ -1,35 +1,72 @@ #include "VariableDeclarationSyntax.h" -#include "ExpressionSyntax.h" -#include "SyntaxToken.h" -#include "TypeClauseSyntax.h" +using namespace Mamba; -namespace Mamba +VariableDeclarationSyntax::VariableDeclarationSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* Keyword, + const SyntaxToken* Identifier, + NullablePointer TypeClause, + const SyntaxToken* EqualsToken, + const ExpressionSyntax* Initializer +) noexcept : + Super(SyntaxTree), + Keyword(Keyword), + Identifier(Identifier), + TypeClause(TypeClause), + EqualsToken(EqualsToken), + Initializer(Initializer) { - VariableDeclarationSyntax::VariableDeclarationSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr Keyword, - const std::shared_ptr Identifier, - const NullableSharedPtr TypeClause, - const std::shared_ptr EqualsToken, - const std::shared_ptr Initializer - ) noexcept : - Super(SyntaxTree), - Keyword(Keyword), - Identifier(Identifier), - TypeClause(TypeClause), - EqualsToken(EqualsToken), - Initializer(Initializer) - { - } +} - SyntaxKind VariableDeclarationSyntax::Kind() const noexcept +VariableDeclarationSyntax::~VariableDeclarationSyntax() noexcept +{ + delete TypeClause; + delete Initializer; +} + +SyntaxKind VariableDeclarationSyntax::Kind() const noexcept +{ + return SyntaxKind::VariableDeclaration; +} + +std::size_t VariableDeclarationSyntax::ChildrenCount() const noexcept +{ + return TypeClause ? 5 : 4; +} + +const SyntaxNode* VariableDeclarationSyntax::ChildAt(std::size_t Index) const noexcept +{ + if (TypeClause) { - return SyntaxKind::VariableDeclaration; + switch (Index) + { + case 0: + return Keyword; + case 1: + return Identifier; + case 2: + return TypeClause; + case 3: + return EqualsToken; + case 4: + return Initializer; + default: + ReportChildrenAccessOutOfBounds(Index); + } } - std::vector> VariableDeclarationSyntax::Children() const noexcept + switch (Index) { - return { Keyword, Identifier, TypeClause, EqualsToken, Initializer }; + case 0: + return Keyword; + case 1: + return Identifier; + case 2: + return EqualsToken; + case 3: + return Initializer; + default: + ReportChildrenAccessOutOfBounds(Index); } -} // namespace Mamba \ No newline at end of file +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/VariableDeclarationSyntax.h b/src/Mamba/Code Analysis/Syntax/VariableDeclarationSyntax.h index d50299b..5bbe486 100644 --- a/src/Mamba/Code Analysis/Syntax/VariableDeclarationSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/VariableDeclarationSyntax.h @@ -1,8 +1,9 @@ #pragma once -#include - +#include "ExpressionSyntax.h" #include "StatementSyntax.h" +#include "SyntaxToken.h" +#include "TypeClauseSyntax.h" namespace Mamba { @@ -12,21 +13,26 @@ namespace Mamba using Super = StatementSyntax; [[nodiscard]] VariableDeclarationSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr Keyword, - const std::shared_ptr Identifier, - const NullableSharedPtr TypeClause, - const std::shared_ptr EqualsToken, - const std::shared_ptr Initializer + const class SyntaxTree* SyntaxTree, + const SyntaxToken* Keyword, + const SyntaxToken* Identifier, + NullablePointer TypeClause, + const SyntaxToken* EqualsToken, + const ExpressionSyntax* Initializer ) noexcept; + ~VariableDeclarationSyntax() noexcept override; + SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::shared_ptr Keyword; - const std::shared_ptr Identifier; - const NullableSharedPtr TypeClause; - const std::shared_ptr EqualsToken; - const std::shared_ptr Initializer; + const SyntaxToken* Keyword; + const SyntaxToken* Identifier; + NullablePointer TypeClause; + const SyntaxToken* EqualsToken; + const ExpressionSyntax* Initializer; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/WhileStatementSyntax.cpp b/src/Mamba/Code Analysis/Syntax/WhileStatementSyntax.cpp index 738a7a0..ad5c5a4 100644 --- a/src/Mamba/Code Analysis/Syntax/WhileStatementSyntax.cpp +++ b/src/Mamba/Code Analysis/Syntax/WhileStatementSyntax.cpp @@ -1,27 +1,44 @@ #include "WhileStatementSyntax.h" -#include "ExpressionSyntax.h" -#include "SyntaxToken.h" +using namespace Mamba; -namespace Mamba +WhileStatementSyntax::WhileStatementSyntax( + const class SyntaxTree* SyntaxTree, + const SyntaxToken* WhileKeyword, + const ExpressionSyntax* Condition, + const StatementSyntax* Body +) noexcept : + Super(SyntaxTree), WhileKeyword(WhileKeyword), Condition(Condition), Body(Body) { - WhileStatementSyntax::WhileStatementSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr WhileKeyword, - const std::shared_ptr Condition, - const std::shared_ptr Body - ) noexcept : - Super(SyntaxTree), WhileKeyword(WhileKeyword), Condition(Condition), Body(Body) - { - } +} - SyntaxKind WhileStatementSyntax::Kind() const noexcept - { - return SyntaxKind::WhileStatement; - } +SyntaxKind WhileStatementSyntax::Kind() const noexcept +{ + return SyntaxKind::WhileStatement; +} - std::vector> WhileStatementSyntax::Children() const noexcept +std::size_t WhileStatementSyntax::ChildrenCount() const noexcept +{ + return 3; +} + +const SyntaxNode* WhileStatementSyntax::ChildAt(std::size_t Index) const noexcept +{ + switch (Index) { - return { WhileKeyword, Condition, Body }; + case 0: + return WhileKeyword; + case 1: + return Condition; + case 2: + return Body; + default: + ReportChildrenAccessOutOfBounds(Index); } -} // namespace Mamba \ No newline at end of file +} + +WhileStatementSyntax::~WhileStatementSyntax() noexcept +{ + delete Condition; + delete Body; +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Syntax/WhileStatementSyntax.h b/src/Mamba/Code Analysis/Syntax/WhileStatementSyntax.h index 42be08d..fa75943 100644 --- a/src/Mamba/Code Analysis/Syntax/WhileStatementSyntax.h +++ b/src/Mamba/Code Analysis/Syntax/WhileStatementSyntax.h @@ -1,8 +1,8 @@ #pragma once +#include "ExpressionSyntax.h" #include "StatementSyntax.h" - -#include +#include "SyntaxToken.h" namespace Mamba { @@ -12,17 +12,22 @@ namespace Mamba using Super = StatementSyntax; [[nodiscard]] WhileStatementSyntax( - const std::shared_ptr SyntaxTree, - const std::shared_ptr WhileKeyword, - const std::shared_ptr Condition, - const std::shared_ptr Body + const class SyntaxTree* SyntaxTree, + const SyntaxToken* WhileKeyword, + const ExpressionSyntax* Condition, + const StatementSyntax* Body ) noexcept; + ~WhileStatementSyntax() noexcept override; + SyntaxKind Kind() const noexcept override; - std::vector> Children() const noexcept override; - const std::shared_ptr WhileKeyword; - const std::shared_ptr Condition; - const std::shared_ptr Body; + const SyntaxToken* WhileKeyword; + const ExpressionSyntax* Condition; + const StatementSyntax* Body; + + private: + std::size_t ChildrenCount() const noexcept override; + const SyntaxNode* ChildAt(std::size_t Index) const noexcept override; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Text/SourceText.cpp b/src/Mamba/Code Analysis/Text/SourceText.cpp index d583934..f8c3124 100644 --- a/src/Mamba/Code Analysis/Text/SourceText.cpp +++ b/src/Mamba/Code Analysis/Text/SourceText.cpp @@ -1,164 +1,138 @@ #include "SourceText.h" +#include "fast_io_core_impl/integers/impl.h" #include "TextLine.h" -#include "TextSpan.h" #include -#include -namespace Mamba +using namespace Mamba; + +[[nodiscard]] constexpr std::size_t GetLineBreakWidth(StringView Text, std::size_t Position) noexcept { - SourceText::SourceText( - const std::shared_ptr Text, - const std::shared_ptr FileName - ) noexcept : - Text(Text), FileName(FileName), Lines(ParseLines(*this, *Text)) + auto Character = Text[Position]; + auto LineBreakCharacter = (Position + 1 >= Text.length() ? TEXT('\0') : Text[Position + 1]); + + if (Character == TEXT('\r') && LineBreakCharacter == TEXT('\n')) { + return 2; } - SourceText SourceText::From( - const std::shared_ptr Text, - const std::shared_ptr FileName - ) noexcept + if (Character == TEXT('\r') || LineBreakCharacter == TEXT('\n')) { - return SourceText(Text, FileName); + return 1; } - std::vector> - SourceText::ParseLines(const SourceText& SourceText, const String& Text) noexcept - { - auto Result = std::vector>(); + return 0; +} +std::size_t SourceText::Length() const noexcept +{ + return PrivateInfo.Text.length(); +} + +std::size_t SourceText::LineIndex(const std::size_t Position) const noexcept +{ #if __cpp_size_t_suffix == 202011L - auto Position = 0uz; - auto LineStart = 0uz; + auto Lower = 0uz; #else - auto Position = std::size_t(); - auto LineStart = std::size_t(); + auto Lower = std::size_t(); #endif + auto Upper = PrivateLines.size() - 1; - while (Position < Text.length()) + while (Lower <= Upper) + { + auto Index = Lower + (Upper - Lower) / 2; + auto Start = PrivateLines[Index].Start; + + if (Position == Start) { - const auto LineBreakWidth = GetLineBreakWidth(Text, Position); - - if (LineBreakWidth == 0) - { - ++Position; - } - else - { - AddLine(Result, SourceText, Position, LineStart, LineBreakWidth); - - Position += LineBreakWidth; - LineStart = Position; - } + return Index; } - if (Position >= LineStart) + if (Start > Position) { - AddLine(Result, SourceText, Position, LineStart, 0); + Upper = Index - 1; + } + else + { + Lower = Index + 1; } - - return Result; } - void SourceText::AddLine( - std::vector>& Result, - const SourceText& SourceText, - const std::size_t Position, - const std::size_t LineStart, - const std::size_t LineBreakWidth - ) noexcept - { - const auto LineLength = Position - LineStart; - const auto LineLengthIncludingLineBreak = LineLength + LineBreakWidth; - const auto Line = std::make_shared( - std::make_shared(SourceText), LineStart, LineLength, LineLengthIncludingLineBreak - ); - Result.emplace_back(Line); - } + return Lower - 1; +} - std::size_t SourceText::GetLineBreakWidth(const String& Text, const std::size_t Position) noexcept - { - const auto Character = Text[Position]; - const auto LineBreakCharacter = (Position + 1 >= Text.length() ? TEXT('\0') : Text[Position + 1]); +const std::vector& SourceText::Lines() const noexcept +{ + return PrivateLines; +} - if (Character == TEXT('\r') && LineBreakCharacter == TEXT('\n')) - { - return 2; - } +StringView SourceText::SubView(std::size_t Start, std::size_t Length) const noexcept +{ + auto End = Start + Length; + auto ViewBegin = PrivateInfo.Text.data() + Start; + auto ViewEnd = PrivateInfo.Text.data() + End; - if (Character == TEXT('\r') || LineBreakCharacter == TEXT('\n')) - { - return 1; - } + return StringView(ViewBegin, ViewEnd); +} - return 0; - } +std::size_t SourceText::RelativeBegin(StringView View) const noexcept +{ + return View.data() - PrivateInfo.Text.data(); +} - std::size_t SourceText::Length() const noexcept - { - return Text->length(); - } +std::size_t SourceText::RelativeEnd(StringView View) const noexcept +{ + return RelativeBegin(View) + View.length(); +} + +SourceText::SourceText(const SourceTextInfo& Info) noexcept : + PrivateInfo(Info) +{ +} + +const SourceTextInfo& SourceText::Info() const noexcept +{ + return PrivateInfo; +} + +std::vector SourceText::SplitLines(const SourceTextInfo& Info) +{ + auto Lines = std::vector(); - std::size_t SourceText::GetLineIndex(const std::size_t Position) const noexcept - { #if __cpp_size_t_suffix == 202011L - auto Lower = 0uz; + auto Position = 0uz; + auto LineStart = 0uz; #else - auto Lower = std::size_t(); + auto Position = std::size_t(); + auto LineStart = std::size_t(); #endif - auto Upper = Lines.size() - 1; - - while (Lower <= Upper) - { - const auto Index = Lower + (Upper - Lower) / 2; - const auto Start = Lines[Index]->Start; - - if (Position == Start) - { - return Index; - } - - if (Start > Position) - { - Upper = Index - 1; - } - else - { - Lower = Index + 1; - } - } - - return Lower - 1; - } - std::shared_ptr SourceText::ToString() const noexcept - { - return Text; - } + const auto& Text = Info.Text; - std::shared_ptr SourceText::ToString(const std::size_t Start, const std::size_t Length) const noexcept + while (Position < Text.length()) { - return std::make_shared(Text->substr(Start, Length)); - } + auto LineBreakWidth = GetLineBreakWidth(Text, Position); + if (LineBreakWidth == 0) + { + ++Position; + } + else + { + auto LineLength = Position - LineStart; + auto LineLengthIncludingLineBreak = LineLength + LineBreakWidth; + Lines.emplace_back(LineStart + 1, LineLength, LineLengthIncludingLineBreak); - std::shared_ptr SourceText::ToString(const TextSpan Span) const noexcept - { - return ToString(Span.Start, Span.Length); + Position += LineBreakWidth; + LineStart = Position; + } } - StringView SourceText::ToView(const std::size_t Start, const std::size_t Length) const noexcept + if (Position >= LineStart) { - const auto End = Start + Length; - const auto ViewBegin = Text->data() + Start; - const auto ViewEnd = Text->data() + End; - - return StringView(ViewBegin, ViewEnd); + auto LineLength = Position - LineStart; + Lines.emplace_back(LineStart, LineLength, LineLength); } - StringView SourceText::ToView(const TextSpan Span) const noexcept - { - return ToView(Span.Start, Span.Length); - } -} // namespace Mamba \ No newline at end of file + return Lines; +} diff --git a/src/Mamba/Code Analysis/Text/SourceText.h b/src/Mamba/Code Analysis/Text/SourceText.h index 0bd95ca..686a789 100644 --- a/src/Mamba/Code Analysis/Text/SourceText.h +++ b/src/Mamba/Code Analysis/Text/SourceText.h @@ -1,68 +1,51 @@ #pragma once -#include "MambaCore.h" -#include "TextSpan.h" - -#include #include +#include "SourceTextInfo.h" +#include "TextLine.h" + namespace Mamba { - class SourceText : public std::enable_shared_from_this + class SourceText { - public: - const std::shared_ptr Text; - const std::shared_ptr FileName; - const std::vector> Lines; - - [[nodiscard]] static SourceText - From(const std::shared_ptr Text, const std::shared_ptr FileName = {}) noexcept; - - [[nodiscard]] SourceText( - const std::shared_ptr Text, - const std::shared_ptr FileName = {} - ) noexcept; - - private: - [[nodiscard]] static std::vector> - ParseLines(const SourceText& SourceText, const String& Text) noexcept; + SourceTextInfo PrivateInfo; + std::vector PrivateLines = SplitLines(PrivateInfo); - static void AddLine( - std::vector>& Result, - const SourceText& SourceText, - const std::size_t Position, - const std::size_t LineStart, - const std::size_t LineBreakWidth - ) noexcept; + public: + [[nodiscard]] SourceText(const SourceTextInfo& Info) noexcept; - [[nodiscard]] static std::size_t GetLineBreakWidth(const String& Text, const std::size_t Position) noexcept; + const SourceTextInfo& Info() const noexcept; - public: -#if __cpp_explicit_this_parameter == 202110L - [[nodiscard]] auto&& operator[](this auto&& Self, const std::size_t Position) noexcept +#if __cpp_explicit_this_parameter >= 202110L + template + [[nodiscard]] auto&& operator[](this SelfT&& Self, std::size_t Position) noexcept { - return (*std::forward(Self).Text)[Position]; + return std::forward_like(Self.PrivateInfo.Text[Position]); } #else - [[nodiscard]] Char operator[](const std::size_t Position) const noexcept + [[nodiscard]] Char operator[](std::size_t Position) const noexcept { - return (*Text)[Position]; + return PrivateInfo.Text[Position]; } #endif [[nodiscard]] std::size_t Length() const noexcept; + [[nodiscard]] std::size_t LineIndex(std::size_t Position) const noexcept; + [[nodiscard]] const std::vector& Lines() const noexcept; - [[nodiscard]] std::size_t GetLineIndex(const std::size_t Position) const noexcept; - - [[nodiscard]] std::shared_ptr ToString() const noexcept; - - [[nodiscard]] std::shared_ptr - ToString(const std::size_t Start, const std::size_t Length) const noexcept; + template + [[nodiscard]] auto&& ToString(this SelfT&& Self) noexcept + { + return std::forward_like(Self.PrivateInfo.Text); + } - [[nodiscard]] std::shared_ptr ToString(const TextSpan Span) const noexcept; + [[nodiscard]] StringView SubView(std::size_t Start, std::size_t Length) const noexcept; - [[nodiscard]] StringView ToView(const std::size_t Start, const std::size_t Length) const noexcept; + [[nodiscard]] std::size_t RelativeBegin(StringView View) const noexcept; + [[nodiscard]] std::size_t RelativeEnd(StringView View) const noexcept; - [[nodiscard]] StringView ToView(const TextSpan Span) const noexcept; + private: + static std::vector SplitLines(const SourceTextInfo& Info); }; -} // namespace Mamba +} // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Text/SourceTextInfo.h b/src/Mamba/Code Analysis/Text/SourceTextInfo.h new file mode 100644 index 0000000..778d3b1 --- /dev/null +++ b/src/Mamba/Code Analysis/Text/SourceTextInfo.h @@ -0,0 +1,12 @@ +#pragma once + +#include "MambaCore.h" + +namespace Mamba +{ + struct SourceTextInfo + { + String FileName; + String Text; + }; +} // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Text/TextLine.cpp b/src/Mamba/Code Analysis/Text/TextLine.cpp index bd2c4e0..956a355 100644 --- a/src/Mamba/Code Analysis/Text/TextLine.cpp +++ b/src/Mamba/Code Analysis/Text/TextLine.cpp @@ -1,36 +1,19 @@ #include "TextLine.h" -#include "SourceText.h" #include "TextSpan.h" -namespace Mamba -{ - TextLine::TextLine( - const std::shared_ptr Text, - const std::size_t Start, - const std::size_t Length, - const std::size_t LengthIncludeLineBreak - ) noexcept : - Text(Text), Start(Start), Length(Length), LengthIncludeLineBreak(LengthIncludeLineBreak) - { - } - - std::size_t TextLine::End() const noexcept - { - return Start + Length; - } +using namespace Mamba; - TextSpan TextLine::Span() const noexcept - { - return TextSpan(Start, Length); - } +std::size_t TextLine::End() const noexcept +{ + return Start + Length; +} - TextSpan TextLine::SpanIncludeLineBreak() const noexcept - { - return TextSpan(Start, LengthIncludeLineBreak); - } +TextSpan TextLine::Span() const noexcept +{ + return TextSpan(Start, Length); +} - std::shared_ptr TextLine::ToString() const noexcept - { - return Text->Text; - } -} // namespace Mamba \ No newline at end of file +TextSpan TextLine::SpanIncludeLineBreak() const noexcept +{ + return TextSpan(Start, LengthIncludeLineBreak); +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Text/TextLine.h b/src/Mamba/Code Analysis/Text/TextLine.h index 7a5eb22..590ca46 100644 --- a/src/Mamba/Code Analysis/Text/TextLine.h +++ b/src/Mamba/Code Analysis/Text/TextLine.h @@ -1,31 +1,18 @@ #pragma once -#include "MambaCore.h" #include -#include namespace Mamba { class TextLine { public: - const std::shared_ptr Text; - const std::size_t Start; - const std::size_t Length; + std::size_t Start; + std::size_t Length; + std::size_t LengthIncludeLineBreak; std::size_t End() const noexcept; - const std::size_t LengthIncludeLineBreak; - struct TextSpan Span() const noexcept; struct TextSpan SpanIncludeLineBreak() const noexcept; - - [[nodiscard]] TextLine( - const std::shared_ptr Text, - const std::size_t Start, - const std::size_t Length, - const std::size_t LengthIncludeLineBreak - ) noexcept; - - [[nodiscard]] std::shared_ptr ToString() const noexcept; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Text/TextLocation.cpp b/src/Mamba/Code Analysis/Text/TextLocation.cpp index 7662d66..2c7fd74 100644 --- a/src/Mamba/Code Analysis/Text/TextLocation.cpp +++ b/src/Mamba/Code Analysis/Text/TextLocation.cpp @@ -1,35 +1,31 @@ #include "TextLocation.h" - #include "SourceText.h" -#include "TextLine.h" -#include "TextSpan.h" -#include +using namespace Mamba; -namespace Mamba +std::size_t TextLocation::StartLine() const noexcept { - std::shared_ptr TextLocation::FileName() const noexcept - { - return Text->FileName; - } + return Text.LineIndex(Text.RelativeBegin(View)); +} - std::size_t TextLocation::StartLine() const noexcept - { - return Text->GetLineIndex(Span.Start); - } +std::size_t TextLocation::AbsoluteStartCharacter() const noexcept +{ + return Text.RelativeBegin(View); +} - std::size_t TextLocation::StartCharacter() const noexcept - { - return Span.Start - Text->Lines[StartLine()]->Start; - } +std::size_t TextLocation::RelativeStartCharacter() const noexcept +{ + auto Line = Text.Lines()[StartLine()]; + return AbsoluteStartCharacter() - Line.Start; +} - std::size_t TextLocation::EndLine() const noexcept - { - return Text->GetLineIndex(Span.End()); - } +std::size_t TextLocation::EndLine() const noexcept +{ + return Text.LineIndex(Text.RelativeEnd(View)); +} - std::size_t TextLocation::EndCharacter() const noexcept - { - return Span.End() - Text->Lines[EndLine()]->Start; - } -} // namespace Mamba \ No newline at end of file +std::size_t TextLocation::AbsoluteEndCharacter() const noexcept +{ + auto Line = Text.Lines()[EndLine()]; + return AbsoluteEndCharacter() - Line.End(); +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Text/TextLocation.h b/src/Mamba/Code Analysis/Text/TextLocation.h index 355693e..d07cf1c 100644 --- a/src/Mamba/Code Analysis/Text/TextLocation.h +++ b/src/Mamba/Code Analysis/Text/TextLocation.h @@ -1,36 +1,26 @@ #pragma once -#include "TextSpan.h" - -#include +#include "SourceText.h" namespace Mamba { struct TextLocation { - std::shared_ptr Text; - TextSpan Span; - - std::shared_ptr FileName() const noexcept; - - /** - * Get the line index of the start line - */ - std::size_t StartLine() const noexcept; - - /** - * Get position of the start character - */ - std::size_t StartCharacter() const noexcept; - - /** - * Get the end line - */ - std::size_t EndLine() const noexcept; - - /** - * Get the end position of the character - */ - std::size_t EndCharacter() const noexcept; + const SourceText& Text; + StringView View; + + template + [[nodiscard]] decltype(auto) FileName(this SelfT&& Self) noexcept + { + return std::forward_like(Self.Text).Info().FileName; + } + + [[nodiscard]] std::size_t StartLine() const noexcept; + [[nodiscard]] std::size_t AbsoluteStartCharacter() const noexcept; + [[nodiscard]] std::size_t RelativeStartCharacter() const noexcept; + + [[nodiscard]] std::size_t EndLine() const noexcept; + [[nodiscard]] std::size_t AbsoluteEndCharacter() const noexcept; + [[nodiscard]] std::size_t RelativeEndCharacter() const noexcept; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Text/TextSpan.cpp b/src/Mamba/Code Analysis/Text/TextSpan.cpp index 3e2bf7c..4605bd2 100644 --- a/src/Mamba/Code Analysis/Text/TextSpan.cpp +++ b/src/Mamba/Code Analysis/Text/TextSpan.cpp @@ -1,28 +1,24 @@ #include "TextSpan.h" -#include -namespace Mamba -{ - TextSpan::TextSpan(const std::size_t Start, const std::size_t Length) noexcept : Start(Start), Length(Length) {} +using namespace Mamba; - std::size_t TextSpan::End() const noexcept - { - return Start + Length; - } +std::size_t TextSpan::End() const noexcept +{ + return Start + Length; +} - TextSpan TextSpan::FromBounds(const std::size_t Start, const std::size_t End) noexcept - { - const auto Length = End - Start; - return TextSpan(Start, Length); - } +TextSpan TextSpan::FromBounds(const std::size_t Start, const std::size_t End) noexcept +{ + const auto Length = End - Start; + return TextSpan(Start, Length); +} - bool TextSpan::OverlapsWith(const TextSpan Span) const noexcept - { - return Start < Span.End() && End() > Span.Start; - } +bool TextSpan::OverlapsWith(const TextSpan Span) const noexcept +{ + return Start < Span.End() && End() > Span.Start; +} - std::shared_ptr TextSpan::ToString() const noexcept - { - return std::make_shared(Concat(Start, TEXT(".."), End())); - } -} // namespace Mamba \ No newline at end of file +String TextSpan::ToString() const noexcept +{ + return Concat(Start, TEXT(".."), End()); +} \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Text/TextSpan.h b/src/Mamba/Code Analysis/Text/TextSpan.h index 67760f3..b2e5c6e 100644 --- a/src/Mamba/Code Analysis/Text/TextSpan.h +++ b/src/Mamba/Code Analysis/Text/TextSpan.h @@ -1,7 +1,6 @@ #pragma once #include "MambaCore.h" -#include namespace Mamba { @@ -10,14 +9,10 @@ namespace Mamba std::size_t Start; std::size_t Length; - [[nodiscard]] std::size_t End() const noexcept; - - [[nodiscard]] TextSpan(const std::size_t Start, const std::size_t Length) noexcept; - static TextSpan FromBounds(const std::size_t Start, const std::size_t End) noexcept; + [[nodiscard]] std::size_t End() const noexcept; [[nodiscard]] bool OverlapsWith(const TextSpan Span) const noexcept; - - [[nodiscard]] std::shared_ptr ToString() const noexcept; + [[nodiscard]] String ToString() const noexcept; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Generation/Backend.h b/src/Mamba/Code Generation/Backend.h new file mode 100644 index 0000000..ba19925 --- /dev/null +++ b/src/Mamba/Code Generation/Backend.h @@ -0,0 +1,15 @@ +#pragma once + +#include "BoundCompilationUnit.h" + +namespace Mamba +{ + template + struct Backend + { + static void GenerateCode(std::span CompilationUnits, StringView ModuleName) noexcept + { + T::GenerateCode(CompilationUnits, ModuleName); + } + }; +} // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Analysis/Emit/Emitter.h b/src/Mamba/Code Generation/Emitter.h similarity index 85% rename from src/Mamba/Code Analysis/Emit/Emitter.h rename to src/Mamba/Code Generation/Emitter.h index eb970cc..699ca41 100644 --- a/src/Mamba/Code Analysis/Emit/Emitter.h +++ b/src/Mamba/Code Generation/Emitter.h @@ -1,7 +1,5 @@ #pragma once -#include - #include "BoundProgram.h" #include "Diagnostic.h" @@ -19,6 +17,6 @@ namespace Mamba Emitter { public: - virtual std::vector Emit(const BoundProgram& Program, const StringView ModuleName) noexcept = 0; + virtual std::vector Emit(const BoundProgram& Program, StringView ModuleName) noexcept = 0; }; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Code Generation/LLVMBackend.cpp b/src/Mamba/Code Generation/LLVMBackend.cpp new file mode 100644 index 0000000..71c5a07 --- /dev/null +++ b/src/Mamba/Code Generation/LLVMBackend.cpp @@ -0,0 +1,16 @@ +#include "LLVMBackend.h" + +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" + +using namespace Mamba; +using namespace llvm; + +void LLVMBackend::GenerateCode(std::span CompilationUnits, std::string_view ModuleName) noexcept +{ + auto Context = LLVMContext(); + auto LLVMModule = Module(ModuleName, Context); + + auto Builder = IRBuilder<>(Context); +} \ No newline at end of file diff --git a/src/Mamba/Code Generation/LLVMBackend.h b/src/Mamba/Code Generation/LLVMBackend.h new file mode 100644 index 0000000..851c28f --- /dev/null +++ b/src/Mamba/Code Generation/LLVMBackend.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#include "Backend.h" + +namespace Mamba +{ + struct LLVMBackend : public Backend + { + static void GenerateCode(std::span CompilationUnits, std::string_view ModuleName) noexcept; + }; +} // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Core/Colors.h b/src/Mamba/Core/Colors.h index b1e0589..3cd03ad 100644 --- a/src/Mamba/Core/Colors.h +++ b/src/Mamba/Core/Colors.h @@ -81,26 +81,24 @@ namespace Mamba .Color = Color }; } - } // namespace FastIO -} // namespace Mamba -namespace fast_io -{ - template - constexpr void print_define(io_reserve_type_t>, auto out [[maybe_unused]], const ::Mamba::ColorT& color) noexcept - { - // \033[m\033[0m - if (color.IsForeground()) + template + constexpr void print_define(fast_io::io_reserve_type_t>, auto out [[maybe_unused]], const ::Mamba::ColorT& color) noexcept { - io::print("\033[", static_cast(color.Color), "m", color.Reference, "\033[39m"); - return; - } - else if (color.IsBackground()) - { - io::print("\033[", static_cast(color.Color), "m", color.Reference, "\033[49m"); - return; + // \033[m\033[0m + if (color.IsForeground()) + { + ::fast_io::io::print(out, "\033[", static_cast(color.Color), "m", color.Reference, "\033[39m"); + return; + } + else if (color.IsBackground()) + { + ::fast_io::io::print(out, "\033[", static_cast(color.Color), "m", color.Reference, "\033[49m"); + return; + } + + std::unreachable(); } + } // namespace FastIO - std::unreachable(); - } -} // namespace fast_io \ No newline at end of file +} // namespace Mamba diff --git a/src/Mamba/Core/DiagnosticPrinter.h b/src/Mamba/Core/DiagnosticPrinter.h new file mode 100644 index 0000000..1c10c65 --- /dev/null +++ b/src/Mamba/Core/DiagnosticPrinter.h @@ -0,0 +1,127 @@ +#pragma once + +#include +#include +#include + +#include "Colors.h" +#include "Diagnostic.h" +#include "MambaCore.h" + +namespace Mamba +{ + constexpr Colors DiagnosticColor(DiagnosticSeverity Severity) noexcept + { + switch (Severity) + { + case DiagnosticSeverity::Error: + return Colors::BrightForegroundRed; + case DiagnosticSeverity::Warning: + return Colors::BrightForegroundYellow; + case DiagnosticSeverity::Information: + return Colors::BrightForegroundCyan; + default: + std::unreachable(); + } + } + + constexpr std::string_view SeverityString(DiagnosticSeverity Severity) noexcept + { + switch (Severity) + { + case DiagnosticSeverity::Error: + return "错误"; + case DiagnosticSeverity::Warning: + return "警告"; + case DiagnosticSeverity::Information: + return "信息"; + default: + std::unreachable(); + } + } + + template + constexpr std::string SourceLocation(const Diagnostic& Diagnostic) noexcept + { + // ::: : + if constexpr (WithColor) + { + auto SeverityColor = DiagnosticColor(Diagnostic.Severity); + auto Severity = SeverityString(Diagnostic.Severity); + + return fast_io::concat( + fast_io::mnp::code_cvt(Diagnostic.Location.FileName()), + ":", + Diagnostic.LineNumber(), + ":", + Diagnostic.Location.RelativeStartCharacter(), + ": ", + Color(Severity, SeverityColor), + Color(": ", SeverityColor), + fast_io::mnp::code_cvt(Diagnostic.Message) + ); + } + + auto Severity = SeverityString(Diagnostic.Severity); + return fast_io::concat( + fast_io::mnp::code_cvt(Diagnostic.Location.FileName()), + ":", + Diagnostic.LineNumber(), + ":", + Diagnostic.Location.RelativeStartCharacter(), + ": ", + Severity, + ": ", + fast_io::mnp::code_cvt(Diagnostic.Message) + ); + } + + constexpr std::string LineView(const Diagnostic& Diagnostic) noexcept + { + // | + return fast_io::concat(" ", Diagnostic.LineNumber(), " | ", fast_io::mnp::code_cvt(Diagnostic.LineView())); + } + + template + constexpr std::string LocationGuide(const Diagnostic& Diagnostic) noexcept + { + constexpr std::string_view PointerCharacter = Fun ? "🤓👆" : "^"; + constexpr std::string_view WaveCharacter = Fun ? "👆" : "~"; + constexpr std::string_view IndentCharacter = " "; + + constexpr auto PointerCharacterSize = Fun ? 2 : 1; + + // 5 = indent (2 spaces) + " | " + auto PrefixIndent = fast_io::concat(Diagnostic.LineNumber()).length() + 5; + auto ContentIndent = Diagnostic.Location.RelativeStartCharacter(); + auto IndentLength = PrefixIndent + ContentIndent; + + auto Indent = std::views::repeat(IndentCharacter, IndentLength) | std::views::join | std::ranges::to(); + + auto Length = Diagnostic.Location.View.size(); + auto WaveLength = Length <= PointerCharacterSize ? 0 : Length - PointerCharacterSize; + auto Wave = std::views::repeat(WaveCharacter, WaveLength) | std::views::join | std::ranges::to(); + + if constexpr (WithColor) + { + return fast_io::concat(Indent, Color(PointerCharacter, Colors::BrightForegroundGreen), Color(Wave, Colors::BrightForegroundGreen)); + } + + return fast_io::concat(Indent, PointerCharacter, Wave); + } + + template + constexpr void print_define(fast_io::io_reserve_type_t, auto out [[maybe_unused]], const Diagnostic& Diagnostic) noexcept + { + using namespace fast_io::io; + + print( + out, + SourceLocation(Diagnostic), + "\n", + LineView(Diagnostic), + "\n", + LocationGuide(Diagnostic) + ); + } +} // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Core/International/Language.h b/src/Mamba/Core/International/Language.h new file mode 100644 index 0000000..ae9b7d8 --- /dev/null +++ b/src/Mamba/Core/International/Language.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +#include + +namespace Mamba +{ + struct LanguageIntermediateRepresentation + { + std::string_view Name; + std::string_view Content; + std::size_t InjectPointCount; + }; + + struct Language + { + std::string_view LanguageCode; + }; + + class LanguageManager + { + public: + static constexpr std::string_view LanguagesFolder = "Languages/"; + + static Language LoadLanguage(std::string_view LanguageCode) noexcept + { + auto LanguageFile = fast_io::concat("Languages/", LanguageCode); + auto FileLoader = fast_io::native_file_loader(LanguageFile); + } + }; +} // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Core/International/LanguageCode.h b/src/Mamba/Core/International/LanguageCode.h new file mode 100644 index 0000000..dda76a3 --- /dev/null +++ b/src/Mamba/Core/International/LanguageCode.h @@ -0,0 +1,11 @@ +#pragma once + +namespace Mamba +{ + // ISO 639-1 language codes + namespace LanguageCodes + { + constexpr auto Chinese = "zh"; + constexpr auto English = "en"; + } // namespace LanguageCodes +} // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/Mamba.cpp b/src/Mamba/Mamba.cpp index b9b8b78..1884f95 100644 --- a/src/Mamba/Mamba.cpp +++ b/src/Mamba/Mamba.cpp @@ -1,144 +1,21 @@ #include "Mamba.h" -#include "Colors.h" -#include "Compilation.h" -#include "Diagnostic.h" -#include "SourceText.h" - -#include -#include -#include -#include +#include "Compiler.h" using namespace Mamba; -using namespace fast_io::io; - -void PrintError(const Diagnostic& Diagnostic) noexcept -{ - println( - Color(fast_io::mnp::code_cvt(*Diagnostic.Location.FileName()), Colors::BrightBackgroundWhite), - Color(":", Colors::BrightBackgroundWhite), - Color(Diagnostic.Location.StartLine(), Colors::BrightBackgroundWhite), - Color(":", Colors::BrightBackgroundWhite), - Color(Diagnostic.Location.StartCharacter(), Colors::BrightBackgroundWhite), - " ", - Color("error: ", Colors::BrightForegroundRed), - Color(fast_io::mnp::code_cvt(Diagnostic.Message), Colors::BrightBackgroundWhite) - ); -} - -void PrintWarning(const Diagnostic& Diagnostic) noexcept -{ - println( - Color(fast_io::mnp::code_cvt(*Diagnostic.Location.FileName()), Colors::BrightBackgroundWhite), - Color(":", Colors::BrightBackgroundWhite), - Color(Diagnostic.Location.StartLine(), Colors::BrightBackgroundWhite), - Color(":", Colors::BrightBackgroundWhite), - Color(Diagnostic.Location.StartCharacter(), Colors::BrightBackgroundWhite), - " ", - Color("warning: ", Colors::BrightForegroundYellow), - Color(fast_io::mnp::code_cvt(Diagnostic.Message), Colors::BrightBackgroundWhite) - ); -} - -void PrintInformation(const Diagnostic& Diagnostic) noexcept -{ - println( - Color(fast_io::mnp::code_cvt(*Diagnostic.Location.FileName()), Colors::BrightBackgroundWhite), - Color(":", Colors::BrightBackgroundWhite), - Color(Diagnostic.Location.StartLine(), Colors::BrightBackgroundWhite), - Color(":", Colors::BrightBackgroundWhite), - Color(Diagnostic.Location.StartCharacter(), Colors::BrightBackgroundWhite), - " ", - Color("note: ", Colors::BrightForegroundCyan), - Color(fast_io::mnp::code_cvt(Diagnostic.Message), Colors::BrightBackgroundWhite) - ); -} - -void PrintDiagnostic(const Diagnostic& Diagnostic) noexcept -{ - switch (Diagnostic.Severity) - { - case DiagnosticSeverity::Error: - PrintError(Diagnostic); - break; - case DiagnosticSeverity::Warning: - PrintWarning(Diagnostic); - break; - case DiagnosticSeverity::Information: - PrintInformation(Diagnostic); - break; - default: - std::unreachable(); - } -} - -void PrintDiagnostics(const std::span Diagnostics) noexcept -{ - if (Diagnostics.empty()) - { - println(Color("Compilation successful", Colors::BrightForegroundGreen)); - return; - } - - for (auto&& Diagnostic : Diagnostics) - { - PrintDiagnostic(Diagnostic); - } -} - -std::shared_ptr ReadFile(std::string_view FileName) noexcept -try -{ - auto FileLoader = fast_io::native_file_loader(FileName); - - const auto Text = std::make_shared(FileLoader.begin(), FileLoader.end()); - auto SharedFileName = std::make_shared(FileName.begin(), FileName.end()); - - return std::make_shared(SourceText::From(Text, SharedFileName)); -} -catch (fast_io::error error) -{ - // error: error reading '': - perrln( - Color("error: ", Colors::BrightForegroundRed), - Color("error reading '", Colors::BrightForegroundWhite), - Color(FileName, Colors::BrightForegroundWhite), - Color("': ", Colors::BrightForegroundWhite), - error - ); - std::exit(-1); -} - -void ProcessInputFiles(const std::span InputFiles) noexcept -{ - auto Sources = std::vector>(); - Sources.reserve(InputFiles.size()); - - for (auto InputFile : InputFiles) - { - Sources.emplace_back(ReadFile(InputFile)); - } - - auto Compilation = ::Mamba::Compilation(Sources); - Compilation.Compile(TEXT("a")); - PrintDiagnostics(Compilation.Diagnostics()); -} std::int32_t Mamba::InitMamba(int ArgumentCount, [[maybe_unused]] char* Arguments[]) noexcept { - if (ArgumentCount <= 1) - { - // mamba: error: no input files - println("mamba: ", Color("error: ", Colors::BrightForegroundRed), Color("no input files", Colors::BrightForegroundWhite)); - return -1; - } + auto Begin = Arguments + 1; + auto End = Arguments + ArgumentCount; + auto ArgumentRange = std::ranges::subrange(Begin, End); - auto InputFiles = std::vector(ArgumentCount); - for (auto Index : std::views::iota(0, ArgumentCount)) + auto Compiler = ::Mamba::Compiler(); + for (auto&& Argument : ArgumentRange) { - InputFiles[Index] = Arguments[Index]; + Compiler.AddSourceFile(std::string_view(Argument)); } - ProcessInputFiles(InputFiles); + + Compiler.Compile(); return 0; } diff --git a/src/Mamba/Mamba.h b/src/Mamba/Mamba.h index 5544fa2..e602ba3 100644 --- a/src/Mamba/Mamba.h +++ b/src/Mamba/Mamba.h @@ -1,10 +1,12 @@ #pragma once -#include "Colors.h" #include #include namespace Mamba { std::int32_t InitMamba(int ArgumentCount, [[maybe_unused]] char* Arguments[]) noexcept; + + // just for fun + constexpr void MambaOut() noexcept {}; } // namespace Mamba \ No newline at end of file diff --git a/src/Mamba/MambaCore.h b/src/Mamba/MambaCore.h index a397a86..d65db98 100644 --- a/src/Mamba/MambaCore.h +++ b/src/Mamba/MambaCore.h @@ -1,6 +1,8 @@ #pragma once +#include "Colors.h" #include +#include #include #include @@ -128,6 +130,23 @@ namespace Mamba std::unreachable(); } + template + [[noreturn]] void InternalCompilerError(std::source_location SourceLocation = std::source_location::current(), T&&... Args) noexcept + { + // ::: internal compiler error: + fast_io::io::perrln( + fast_io::mnp::os_c_str(SourceLocation.file_name()), + ":", + SourceLocation.line(), + ":", + SourceLocation.column(), + ": ", + Color("internal compiler error: ", Colors::BrightForegroundRed), + std::forward(Args)... + ); + fast_io::fast_terminate(); + } + // Hatcher stores a callable object, so that the result of the call can be emplace constructed into a container by // copy elision, the container must support adding new elements by forwarding arguments to the constructor // (emplace). diff --git a/xmake.lua b/xmake.lua index 491b699..2e67ee3 100644 --- a/xmake.lua +++ b/xmake.lua @@ -1,19 +1,60 @@ add_rules("mode.debug", "mode.release") add_rules("plugin.compile_commands.autoupdate") +local includedirs = { + "src/Mamba", + "src/Mamba/Core", + "src/Mamba/Code Analysis", + "src/Mamba/Code Analysis/Syntax", + "src/Mamba/Code Analysis/Text", + "src/Mamba/Code Analysis/Binding", + "src/Mamba/Code Analysis/Symbol", + "src/Mamba/Code Generation", +} + +rule("libllvm") +do + on_config(function (target) + import("lib.detect.find_tool") + local llvm_config = find_tool("llvm-config") + + -- local cflags_raw = os.iorunv(llvm_config.program, { "--cflags" }) + -- local cppflags_raw = os.iorunv(llvm_config.program, { "--cppflags" }) + -- local cxxflags_raw = os.iorunv(llvm_config.program, { "--cxxflags" }) + local ldflags_raw = os.iorunv(llvm_config.program, { "--ldflags" }) + local libflags_raw = os.iorunv(llvm_config.program, { "--libs" }) + + -- local cflags = cflags_raw:split("%s+") or {} + -- local cppflags = cppflags_raw:split("%s+") or {} + -- local cxxflags = cxxflags_raw:split("%s+") or {} + local ldflags = ldflags_raw:split("%s+") or {} + local libflags = libflags_raw:split("%s+") or {} + + -- target:add("cflags", cflags) + -- target:add("cxflags", cppflags) + target:add("cxxflags", cxxflags) + target:add("ldflags", ldflags) + target:add("ldflags", libflags_raw, {force = true}) + end) +end +rule_end() + add_requires("fast_io") +add_rules("libllvm") target("Jvav") set_kind("binary") add_files("src/Mamba/**.cpp") add_headerfiles("src/Mamba/**.h") - set_languages("clatest", "c++latest") add_packages("fast_io") set_toolchains("llvm") + set_filename("mamba") + add_languages("clatest", "c++latest") set_warnings("all", "extra") - add_includedirs("src/Mamba", "src/Mamba/Core", "src/Mamba/Code Analysis", "src/Mamba/Code Analysis/Syntax", "src/Mamba/Code Analysis/Text", "src/Mamba/Code Analysis/Binding", "src/Mamba/Code Analysis/Symbol", "src/Mamba/Code Analysis/Emit", "src/Mamba/Code Analysis/Linking") + add_includedirs(includedirs) if is_os("macosx") then add_linkdirs("/opt/homebrew/opt/llvm/lib/c++") -- macOS compability + add_includedirs("/opt/homebrew/opt/llvm/include") end if is_mode("release") then set_optimize("fastest") @@ -25,6 +66,16 @@ target("Jvav") add_defines("DEBUG") end + -- add_includedirs("/opt/homebrew/opt/llvm/include") + -- add_cxxflags("$(shell " .. llvm_config .. " --cxxflags)") + -- add_ldflags("$(shell " .. llvm_config .. " --ldflags)") + -- add_ldflags("$(shell " .. llvm_config .. " --libs all)", {force=true}) + -- add_cxxflags("-march=native") + -- add_syslinks("$(shell " .. llvm_config .. " --system-libs)") + +target_end() + + for _, file in ipairs(os.files("src/Test/**.cpp")) do local name = path.basename(file) target(name) @@ -33,78 +84,8 @@ for _, file in ipairs(os.files("src/Test/**.cpp")) do add_files("src/Mamba/**.cpp") add_headerfiles("src/Mamba/**.h") set_languages("clatest", "c++latest") - add_includedirs("src/Mamba", "src/Mamba/Core", "src/Mamba/Code Analysis", "src/Mamba/Code Analysis/Syntax", "src/Mamba/Code Analysis/Text", "src/Mamba/Code Analysis/Binding", "src/Mamba/Code Analysis/Symbol", "src/Mamba/Code Analysis/Emit", "src/Mamba/Code Analysis/Linking") + add_includedirs(includedirs) add_files("src/Test/" .. name .. ".cpp") add_packages("fast_io") add_tests("default") -end - --- --- If you want to known more usage about xmake, please see https://xmake.io --- --- ## FAQ --- --- You can enter the project directory firstly before building project. --- --- $ cd projectdir --- --- 1. How to build project? --- --- $ xmake --- --- 2. How to configure project? --- --- $ xmake f -p [macosx|linux|iphoneos ..] -a [x86_64|i386|arm64 ..] -m [debug|release] --- --- 3. Where is the build output directory? --- --- The default output directory is `./build` and you can configure the output directory. --- --- $ xmake f -o outputdir --- $ xmake --- --- 4. How to run and debug target after building project? --- --- $ xmake run [targetname] --- $ xmake run -d [targetname] --- --- 5. How to install target to the system directory or other output directory? --- --- $ xmake install --- $ xmake install -o installdir --- --- 6. Add some frequently-used compilation flags in xmake.lua --- --- @code --- -- add debug and release modes --- add_rules("mode.debug", "mode.release") --- --- -- add macro definition --- add_defines("NDEBUG", "_GNU_SOURCE=1") --- --- -- set warning all as error --- set_warnings("all", "error") --- --- -- set language: c99, c++11 --- set_languages("c99", "c++11") --- --- -- set optimization: none, faster, fastest, smallest --- set_optimize("fastest") --- --- -- add include search directories --- add_includedirs("/usr/include", "/usr/local/include") --- --- -- add link libraries and search directories --- add_links("tbox") --- add_linkdirs("/usr/local/lib", "/usr/lib") --- --- -- add system link libraries --- add_syslinks("z", "pthread") --- --- -- add compilation and link flags --- add_cxflags("-stdnolib", "-fno-strict-aliasing") --- add_ldflags("-L/usr/local/lib", "-lpthread", {force = true}) --- --- @endcode --- - +end \ No newline at end of file