require_relative '../task_helper'

namespace :builtins do
  task :glsl do
    GLSLBuiltins.process('./lib/rouge/lexers/glsl/builtins.rb')
  end
end

class GLSLBuiltins < BuiltinsGenerator
  FUNCTIONS_ADOC = 'https://raw.githubusercontent.com/KhronosGroup/GLSL/refs/heads/main/chapters/builtinfunctions.adoc'
  BASICS_ADOC = 'https://raw.githubusercontent.com/KhronosGroup/GLSL/refs/heads/main/chapters/basics.adoc'
  VARIABLES_ADOC = 'https://github.com/KhronosGroup/GLSL/blob/main/chapters/variables.adoc'
  BUILTINS_ADOC = 'https://raw.githubusercontent.com/KhronosGroup/GLSL/refs/heads/main/chapters/builtins.adoc'

  def fetch
    [
      URI.open(FUNCTIONS_ADOC).read,
      URI.open(BASICS_ADOC).read,
      URI.open(VARIABLES_ADOC).read,
      URI.open(BUILTINS_ADOC).read,
    ]

    # [jneen] alternate option for testing when ratelimited by Github
    # [
    #   File.read('/tmp/builtinfunctions.adoc'),
    #   File.read('/tmp/basics.adoc'),
    #   File.read('/tmp/variables.adoc'),
    #   File.read('/tmp/builtins.adoc'),
    # ]
  end

  def parse_sections(text)
    text.gsub!(/^(ifdef|endif)::.*$/, '')

    sections = {}
    text.scan(/\[\[([\w-]+)\]\]\n(.*?)(?=\[\[|\z)/m).each do |(header, text)|
      sections[header] = text
    end

    sections
  end

  def parse
    functions, basics, variables, builtins = @input

    variables = parse_sections(variables)
    basics = parse_sections(basics)

    out = {}

    out[:builtins] = functions.scan(/\w+ (\w+)[(]/).flatten.sort.uniq

    # false positives
    out[:builtins] -= ['ComputeAccessedLod', '_', 'array']

    out[:types] = variables['basic-types'].scan(/[*](\w+)[*]/).flatten.sort.uniq

    out[:keywords] = basics['keywords'].scan(/[*](\w+)[*]/).flatten.sort.uniq

    out[:glvars] = builtins.scan(/\b_(gl_\w+)_\b/).flatten
    out[:glvars] += builtins.scan(/\bgl_\w+\b/).flatten
    out[:glvars].sort!
    out[:glvars].uniq!

    # make unique
    out[:keywords] -= out[:types]
    out[:builtins] -= out[:keywords]
    out[:builtins] -= out[:types]

    out
  end

  def generate
    yield   "# -*- coding: utf-8 -*- #"
    yield   "# frozen_string_literal: true"
    yield   ""
    yield   "# DO NOT EDIT"
    yield   "# This file is automatically generated by `rake builtins:glsl`."
    yield   "# See tasks/builtins/glsl.rake for more info."
    yield   ""
    yield   "module Rouge"
    yield   "  module Lexers"
    yield   "    class GLSL"
    yield   "      BUILTINS = Set#{@keywords[:builtins].inspect}"
    yield   "      KEYWORDS = Set#{@keywords[:keywords].inspect}"
    yield   "      TYPES = Set#{@keywords[:types].inspect}"
    yield   "      GL_VARS = Set#{@keywords[:glvars].inspect}"
    yield   "    end"
    yield   "  end"
    yield   "end"
  end
end
