diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 44ec6cb..def5259 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,6 +20,7 @@ jobs: - uses: actions/checkout@v4 with: persist-credentials: false + submodules: true - name: Set up Ruby uses: ruby/setup-ruby@v1 with: diff --git a/.gitmodules b/.gitmodules index 4e3fc4e..7702456 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "vendor/spinel"] path = vendor/spinel url = https://github.com/matz/spinel + branch = self-host diff --git a/.rubocop.yml b/.rubocop.yml index ae378d0..a29cd67 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,5 +1,19 @@ AllCops: TargetRubyVersion: 3.2 + NewCops: disable + Exclude: + - "vendor/**/*" + - "examples/**/*.rb" + - "lib/rubyduino/arduino_uno.rb" + - "lib/rubyduino/spinel_arduino_codegen.rb" + +Metrics/MethodLength: + Exclude: + - "bin/rubyduino" + +Style/SoleNestedConditional: + Exclude: + - "bin/rubyduino" Style/StringLiterals: EnforcedStyle: double_quotes diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f246a3..46a6807 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ ## [Unreleased] +## [0.2.1] - 2026-08-19 + +- Update vendored Spinel to `b80ba94b` from the compatible `self-host` branch +- Adapt Arduino code generation to Spinel's separate analysis and codegen pipeline +- Add the `sp_Class` value type and integer arithmetic helpers required by the updated code generator to the AVR runtime + ## [0.2.0] - 2026-05-08 - Expand the ArduinoUNO API with PWM, microsecond delays, millis/micros timing, pulse measurement, serial I/O, shift helpers, and interrupt control diff --git a/lib/rubyduino/sp_runtime.h b/lib/rubyduino/sp_runtime.h index 2769cab..af50d7e 100644 --- a/lib/rubyduino/sp_runtime.h +++ b/lib/rubyduino/sp_runtime.h @@ -19,6 +19,15 @@ typedef struct { mrb_int last; } sp_Range; +typedef struct { + mrb_int cls_id; +} sp_Class; + +#define sp_int_add(a, b) ((mrb_int)((a) + (b))) +#define sp_int_sub(a, b) ((mrb_int)((a) - (b))) +#define sp_int_mul(a, b) ((mrb_int)((a) * (b))) +#define sp_int_neg(a) ((mrb_int)(-(a))) + #ifndef TRUE #define TRUE 1 #endif diff --git a/lib/rubyduino/spinel.rb b/lib/rubyduino/spinel.rb index b187d01..c4dbd28 100644 --- a/lib/rubyduino/spinel.rb +++ b/lib/rubyduino/spinel.rb @@ -2,7 +2,7 @@ module Rubyduino module Spinel - COMMIT = "e7f714f213ca572912f7214f358a927f8e2152e5" + COMMIT = "b80ba94b7163e822b34758b1de1555a3da32374b" ROOT = File.expand_path("../../vendor/spinel", __dir__) end end diff --git a/lib/rubyduino/spinel_arduino_codegen.rb b/lib/rubyduino/spinel_arduino_codegen.rb index 940cf04..1739e73 100644 --- a/lib/rubyduino/spinel_arduino_codegen.rb +++ b/lib/rubyduino/spinel_arduino_codegen.rb @@ -1,9 +1,12 @@ #!/usr/bin/env ruby # Arduino UNO codegen layer for Spinel. # -# This file intentionally leaves spinel_codegen.rb unchanged. Spinel's codegen -# file is CLI-oriented, so we load only its Compiler definition and keep the -# same AST-file input/output-file flow as the upstream footer. +# This file intentionally leaves Spinel's analyzer and code generator unchanged. +# It runs the upstream analysis phase, then loads only the Compiler definition +# from the CLI-oriented code generator before applying the Arduino extensions. + +require "rbconfig" +require "tempfile" ROOT = File.expand_path("../..", __dir__) SPINEL_ROOT = File.join(ROOT, "vendor/spinel") @@ -11,7 +14,7 @@ def load_spinel_compiler path = File.join(SPINEL_ROOT, "spinel_codegen.rb") source = File.read(path) - marker = "\n# ---- Main ----\n" + marker = "\n# ---- Main (codegen) ----\n" split_at = source.index(marker) unless split_at warn "spinel_arduino_codegen: cannot find codegen main marker" @@ -106,13 +109,20 @@ def integer_literal_node?(nid) exit(1) end -compiler = Compiler.new -compiler.read_text_ast(File.read(ast_file)) -compiler.compile - -result = compiler.build_output -if out_file - File.write(out_file, result) -else - print result +analyzer = File.join(SPINEL_ROOT, "spinel_analyze.rb") +Tempfile.create(["spinel-analysis", ".ir"]) do |ir_file| + ir_file.close + abort "spinel_arduino_codegen: analysis failed" unless system(RbConfig.ruby, analyzer, ast_file, ir_file.path) + + compiler = Compiler.new + compiler.read_text_ast(File.read(ast_file)) + compiler.load_analysis_buf(File.read(ir_file.path)) + compiler.generate_code + + result = compiler.build_output + if out_file + File.write(out_file, result) + else + print result + end end diff --git a/lib/rubyduino/version.rb b/lib/rubyduino/version.rb index d512231..10fc7d4 100644 --- a/lib/rubyduino/version.rb +++ b/lib/rubyduino/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Rubyduino - VERSION = "0.2.0" + VERSION = "0.2.1" end diff --git a/rubyduino.gemspec b/rubyduino.gemspec index abb4afa..ae169c2 100644 --- a/rubyduino.gemspec +++ b/rubyduino.gemspec @@ -9,7 +9,8 @@ Gem::Specification.new do |spec| spec.email = ["joseph.schito@gmail.com"] spec.summary = "Compile Ruby sketches for Arduino boards." - spec.description = "Rubyduino compiles Ruby code for Arduino boards and uploads the generated firmware over a serial port." + spec.description = "Rubyduino compiles Ruby code for Arduino boards " \ + "and uploads the generated firmware over a serial port." spec.homepage = "https://github.com/josephschito/rubyduino" spec.license = "MIT" spec.required_ruby_version = ">= 3.2.0" @@ -27,7 +28,7 @@ Gem::Specification.new do |spec| (f == gemspec) || (f == "vendor/spinel") || f.start_with?(*%w[Gemfile .gitignore test/ .github/ .rubocop.yml]) || - (%w[bin/console bin/setup].include?(f)) + %w[bin/console bin/setup].include?(f) end end diff --git a/test/test_rubyduino.rb b/test/test_rubyduino.rb index a1b9b06..5e3a0ac 100644 --- a/test/test_rubyduino.rb +++ b/test/test_rubyduino.rb @@ -8,7 +8,7 @@ def test_that_it_has_a_version_number end def test_spinel_snapshot_is_available - assert_equal "e7f714f213ca572912f7214f358a927f8e2152e5", Rubyduino::Spinel::COMMIT + assert_equal "b80ba94b7163e822b34758b1de1555a3da32374b", Rubyduino::Spinel::COMMIT assert_path_exists File.join(Rubyduino::Spinel::ROOT, "README.md") end @@ -18,6 +18,7 @@ def test_gemspec_packages_spinel_files assert_includes spec.files, "bin/rubyduino" assert_includes spec.files, "lib/rubyduino/spinel_arduino_codegen.rb" assert_includes spec.files, "vendor/spinel/README.md" + assert_includes spec.files, "vendor/spinel/spinel_analyze.rb" assert_includes spec.files, "vendor/spinel/spinel_codegen.rb" refute_includes spec.files, "vendor/spinel/.git" end diff --git a/vendor/spinel b/vendor/spinel index e7f714f..b80ba94 160000 --- a/vendor/spinel +++ b/vendor/spinel @@ -1 +1 @@ -Subproject commit e7f714f213ca572912f7214f358a927f8e2152e5 +Subproject commit b80ba94b7163e822b34758b1de1555a3da32374b