# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
name: D

on:
  push:
    branches: [ "**" ]
  pull_request:
    branches: [ "**" ]
  workflow_dispatch:

permissions:
  contents: read

jobs:
  build:
    name: Build
    strategy:
      matrix:
        os: [ubuntu-latest]
        dc: [dmd-latest]
        exclude:
          - { os: macOS-latest, dc: dmd-latest }

    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v2
      
      
      - name: Install D compiler
        uses: dlang-community/setup-dlang@v1
        with:
          compiler: ${{ matrix.dc }}

      - name: Build
        run: dub build
        
      
        
      - uses: actions/upload-artifact@v3
        with:
          name: tbin
          path: tlang

  unittests:
    needs: build
    name: Unit tests
    strategy:
      matrix:
        os: [ubuntu-latest]
        dc: [dmd-2.101.0]
        exclude:
          - { os: macOS-latest, dc: dmd-2.085.0 }
    runs-on: ${{ matrix.os }}
    
    
    
    steps:
      - uses: actions/checkout@v2
      - name: Install D compiler
        uses: dlang-community/setup-dlang@v1
        with:
          compiler: ${{ matrix.dc }}
          ref: ${{ github.head_ref }}

      - name: Install Doveralls (code coverage tool)
        run: |
          # wget -O doveralls "https://github.com/ColdenCullen/doveralls/releases/download/v1.1.5/doveralls_linux_travis"
          # mv doveralls_linux_travis doveralls
          # chmod +x doveralls
          dub fetch doveralls
          sudo apt update
          sudo apt install libcurl4-openssl-dev
        
      - name: DUB unit tests with coverage
        run: dub test --coverage

      - name: Coverage upload
        run: |
          dub run doveralls -- -t ${{secrets.COVERALLS_REPO_TOKEN}}
        
      - uses: actions/upload-artifact@v3
        with:
          name: coverage files
          path: \*.lst

  syntaxcheck:
    needs: [build, unittests]
    name: Syntax checking (fine typecheck home)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Download tlang compiler
        uses: actions/download-artifact@v3
        with:
          name: tbin
        
      - name: Chmod compiler
        run: chmod +x tlang
      # TODO: Maybe check below and make them typeheck again
      - name: Simple float constant
        run: ./tlang syntaxcheck source/tlang/testing/typecheck/simple_float_constant.t
      - name: Simple float constant bad
        run: |
          set +e
          ./tlang syntaxcheck source/tlang/testing/typecheck/simple_float_constant_bad.t
          if [ $? = 255 ]
          then
              exit 0
          else
              exit 1
          fi
      - name: Simple string
        run: ./tlang syntaxcheck source/tlang/testing/typecheck/simple_string.t
      
      - name: Simple return (good)
        run: |
          ./tlang syntaxcheck source/tlang/testing/return/simple_return_good.t
      - name: Simple return (bad return position)
        run: |
          set +e
          ./tlang syntaxcheck source/tlang/testing/return/simple_return_bad.t
          if [ $? = 255 ]
          then
              exit 0
          else
              exit 1
          fi


      - name: Simple return (expressionless)
        run: ./tlang syntaxcheck source/tlang/testing/return/simple_return_expressionless.t

  typecheck:
    needs: [build, unittests]
    name: Typechecking tests
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Download tlang compiler
        uses: actions/download-artifact@v3
        with:
          name: tbin
        
      - name: Chmod compiler
        run: chmod +x tlang
        

      - name: Simple return (expressionless)
        run: ./tlang typecheck source/tlang/testing/return/simple_return_expressionless.t

      - name: Simple return (with expression)
        run: ./tlang typecheck source/tlang/testing/return/simple_return_type.t

      
        
      - name: Simple function call
        run: ./tlang typecheck source/tlang/testing/typecheck/simple_function_call.t
      - name: Simple function call 1 (type mismatch)
        run: |
          set +e
          ./tlang typecheck source/tlang/testing/typecheck/simple_function_call_1.t
          if [ $? = 255 ]
          then
              exit 0
          else
              exit 1
          fi

      # Array support
      - name: Simple array
        run: ./tlang typecheck source/tlang/testing/simple_arrays.t
      - name: Simple array 2
        run: ./tlang typecheck source/tlang/testing/simple_arrays2.t
      - name: Simple array 4
        run: ./tlang typecheck source/tlang/testing/simple_arrays4.t

      - name: Stack-based array coercion
        run: ./tlang typecheck source/tlang/testing/simple_stack_array_coerce.t
      - name: Complex stack-based arrays
        run: ./tlang typecheck source/tlang/testing/complex_stack_arrays1.t
      - name: Stack-based array coercion (type mismatch)
        run: |
          set +e
          ./tlang compile source/tlang/testing/simple_stack_array_coerce_wrong.t
          if [ $? = 255 ]
          then
              exit 0
          else
              exit 1
          fi

      - name: Stack-based array coercion (good permutations))
        run: |
          ./tlang typecheck source/tlang/testing/complex_stack_array_coerce_permutation_good.t
      - name: Stack-based array coercion (type mismatch - bad permutation 1)
        run: |
          set +e
          ./tlang compile source/tlang/testing/complex_stack_array_coerce_bad1.t
          if [ $? = 255 ]
          then
              exit 0
          else
              exit 1
          fi
      - name: Stack-based array coercion (type mismatch - bad permutation 2)
        run: |
          set +e
          ./tlang compile source/tlang/testing/complex_stack_array_coerce_bad2.t
          if [ $? = 255 ]
          then
              exit 0
          else
              exit 1
          fi
      - name: Stack-based array coercion (type mismatch - bad permutation 3)
        run: |
          set +e
          ./tlang compile source/tlang/testing/complex_stack_array_coerce_bad3.t
          if [ $? = 255 ]
          then
              exit 0
          else
              exit 1
          fi
        
      - name: Collide container module1
        run: |
          set +e
          ./tlang typecheck source/tlang/testing/collide_container_module1.t
          if [ $? = 255 ]
          then
              exit 0
          else
              exit 1
          fi
      - name: Collide container module2
        run: |
          set +e
          ./tlang typecheck source/tlang/testing/collide_container_module2.t
          if [ $? = 255 ]
          then
              exit 0
          else
              exit 1
          fi
      - name: Collide container non-module
        run: |
          set +e
          ./tlang typecheck source/tlang/testing/collide_container_non_module.t
          if [ $? = 255 ]
          then
              exit 0
          else
              exit 1
          fi
      - name: Collide container
        run: |
          set +e
          ./tlang typecheck source/tlang/testing/collide_container.t
          if [ $? = 255 ]
          then
              exit 0
          else
              exit 1
          fi
      - name: Collide member
        run: |
          set +e
          ./tlang typecheck source/tlang/testing/collide_member.t
          if [ $? = 255 ]
          then
              exit 0
          else
              exit 1
          fi
      - name: Precedence collision test
        run: |
          set +e
          ./tlang typecheck source/tlang/testing/precedence_collision_test.t
          if [ $? = 255 ]
          then
              exit 0
          else
              exit 1
          fi
        
      - name: Else if without if
        run: |
          set +e
          ./tlang typecheck source/tlang/testing/else_if_without_if.pl
          if [ $? = 255 ]
          then
              exit 0
          else
              exit 1
          fi
          
      - name: Simple module positive
        run: ./tlang typecheck source/tlang/testing/simple1_module_positive.t
      # TODO: Re-enable OOP when we start focusing on it again  
      #- name: Simple OOP
      #  run: ./tlang typecheck source/tlang/testing/simple1_oop.t
      - name: Simple name recognition
        run: ./tlang typecheck source/tlang/testing/simple2_name_recognition.t
      # TODO: Re-enable OOP when we start focusing on it again 
      #- name: test3
      #  run: ./tlang typecheck source/tlang/testing/test3.t
        
      - name: Simple literals
        run: ./tlang typecheck source/tlang/testing/simple_literals.t
      - name: Simple literals 2 (uncoercible)
        run: |
          set +e
          ./tlang typecheck source/tlang/testing/simple_literals2.t
          if [ $? = 255 ]
          then
              exit 0
          else
              exit 1
          fi
      - name: Simple literals 3
        run: ./tlang typecheck source/tlang/testing/simple_literals3.t
      - name: Simple literals 4 (range violation)
        run:
          set +e
          ./tlang typecheck source/tlang/testing/simple_literals4.t
          if [ $? = 255 ]
          then
              exit 0
          else
              exit 1
          fi
      - name: Simple literals 5
        run: ./tlang typecheck source/tlang/testing/simple_literals5.t
      - name: Simple literals 6
        run: ./tlang typecheck source/tlang/testing/simple_literals6.t



      # All the universal coercion tests are below
      #
      # Over time those above will be ported over to it and will
      # infact make part of the test suite of typeEnforce()
      - name: Simple Coerce Literal Good (to variable declaration)
        run: ./tlang typecheck source/tlang/testing/universal_coerce/simple_coerce_literal_good.t
      - name: Simple Coerce Literal Bad [Size loss] (to variable declaration)
        run:
          set +e
          ./tlang typecheck source/tlang/testing/universal_coerce/simple_coerce_literal_bad.t
          if [ $? = 255 ]
          then
              exit 0
          else
              exit 1
          fi

      - name: Simple Coerce Literal Good (standalone variable assignment)
        run: ./tlang typecheck source/tlang/testing/universal_coerce/simple_coerce_literal_good_stdalo.t
      - name: Simple Coerce Literal Bad [Size loss] (standalone variable assignment)
        run:
          set +e
          ./tlang typecheck source/tlang/testing/universal_coerce/simple_coerce_literal_bad_stdalon.t
          if [ $? = 255 ]
          then
              exit 0
          else
              exit 1
          fi

      - name: Function return expression coercion (good)
        run: ./tlang typecheck source/tlang/testing/simple_function_return_type_check_good.t
      - name: Function return expression coercion (bad)
        run:
          set +e
          ./tlang typecheck source/tlang/testing/simple_function_return_type_check_bad.t
          if [ $? = 255 ]
          then
              exit 0
          else
              exit 1
          fi
        
  emit:
    needs: [build, unittests]
    name: Emit tests
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Download tlang compiler
        uses: actions/download-artifact@v3
        with:
          name: tbin
        
      - name: Chmod compiler
        run: chmod +x tlang


      - name: Simple functions
        run: |
          ./tlang compile source/tlang/testing/simple_functions.t
          ./tlang.out
      - name: Simple functions (statement-level)
        run: |
          ./tlang compile source/tlang/testing/simple_direct_func_call.t
          ./tlang.out
      - name: Simple functions (recursive)
        run: |
          ./tlang compile source/tlang/testing/simple_function_recursion_factorial.t
          ./tlang.out



      # TODO: Re-enable when we support the `discard` keyword again
      #- name: Simple variables
      #  run: |
      #    ./tlang compile source/tlang/testing/simple_variables.t
      #    ./tlang.out
      - name: Simple conditions
        run: |
          ./tlang compile source/tlang/testing/simple_conditionals.t
          ./tlang.out
      - name: Nested conditionals
        run: |
          ./tlang compile source/tlang/testing/nested_conditionals.t
          ./tlang.out
      - name: Simple function decls
        run: |
          ./tlang compile source/tlang/testing/simple_function_decls.t
          ./tlang.out
      - name: Simple variables (only) decls
        run: |
          ./tlang compile source/tlang/testing/simple_variables_only_decs.t
          ./tlang.out
      - name: Simple variables decls assignment
        run: |
          ./tlang compile source/tlang/testing/simple_variables_decls_ass.t
          ./tlang.out
      - name: Simple while
        run: |
          ./tlang compile source/tlang/testing/simple_while.t
          ./tlang.out
      #- name: Simple do-while
      #  run: |
      #    ./tlang compile source/tlang/testing/simple_do_while.t
      #    ./tlang.out
      - name: Simple for-loops
        run: |
          ./tlang compile source/tlang/testing/simple_for_loops.t
          ./tlang.out
      - name: Simple cast
        run: |
          ./tlang compile source/tlang/testing/simple_cast.t
          ./tlang.out
      - name: Simple pointer
        run: |
          ./tlang compile source/tlang/testing/simple_pointer.t
          ./tlang.out
      - name: Simple pointer cast (little endian)
        run: |
          ././tlang compile source/tlang/testing/simple_pointer_cast_le.t
          ./tlang.out
      - name: Simple extern
        run: |
          chmod +x extern_test.sh
          ./extern_test.sh


      # Array support
      - name: Stack-based arrays simple
        run: |
          ./tlang compile source/tlang/testing/simple_stack_arrays4.t
          ./tlang.out
      - name: Stack-based array coercion (array syntax)
        run: |
          ./tlang compile source/tlang/testing/simple_stack_array_coerce.t
          ./tlang.out
      - name: Stack-based array coercion (pointer syntax)
        run: |
          ./tlang compile source/tlang/testing/simple_stack_array_coerce_ptr_syntax.t
          ./tlang.out
      - name: Stack-based array with normal array coercion (complex)
        run: |
          ./tlang compile source/tlang/testing/complex_stack_array_coerce.t
          ./tlang.out


      # TODO: Actually add semantic tests for these
      - name: Complex stack-based arrays
        run: |
          ./tlang compile source/tlang/testing/complex_stack_arrays1.t
          ./tlang.out
      - name: Simple array
        run: |
          ./tlang compile source/tlang/testing/simple_arrays.t
          ./tlang.out
      - name: Simple array 2
        run: |
          ./tlang compile source/tlang/testing/simple_arrays2.t
          ./tlang.out
      - name: Simple array 4
        run: |
          ./tlang compile source/tlang/testing/simple_arrays4.t
          ./tlang.out


      - name: Simple pointer (malloc and free)
        run: |
          chmod +x malloc_test.sh
          ./malloc_test.sh
      - name: Simple pointer (array syntax)
        run: |
          ./tlang compile source/tlang/testing/simple_pointer_array_syntax.t
          ./tlang.out



##################################
####### Deployment section #######
##################################

#   deploy:
#     needs: [build, unittests, typecheck, syntaxcheck, emit]
#     name: Deply alpha build
#     runs-on: ubuntu-latest
#     steps:
#       - uses: actions/checkout@v2
#       - name: Download tlang compiler
#         uses: actions/download-artifact@v3
#         with:
#           name: tbin
        
#       - uses: "marvinpinto/action-automatic-releases@latest"
#         with:
#           repo_token: "${{ secrets.YES_TOKEN_DEPLOY }}"
#           automatic_release_tag: "latest"
#           prerelease: true
#           title: "Development Build"
#           files: |
#             tbin  
        


      
