Module: MilkTea::AST

Defined in:
lib/milk_tea/core/ast.rb

Defined Under Namespace

Classes: AlignofExpr, Argument, Assignment, AttributeApplication, AttributeDecl, AwaitExpr, BinaryOp, BooleanLiteral, BreakStmt, Call, CharLiteral, CompilerFlagDirective, ConstDecl, ContinueStmt, DeferStmt, DetachExpr, DynType, EmitStmt, EnumDecl, EnumMember, ErrorBlockStmt, ErrorExpr, ErrorStmt, EventDecl, ExpressionList, ExpressionStmt, ExtendingBlock, ExternFunctionDecl, Field, FlagsDecl, FloatLiteral, ForBinding, ForStmt, ForeignFunctionDecl, ForeignParam, FormatExprPart, FormatString, FormatTextPart, FunctionDef, FunctionType, GatherStmt, Identifier, IfBranch, IfExpr, IfStmt, Import, IncludeDirective, IndexAccess, IntegerLiteral, InterfaceDecl, InterfaceMethodDecl, LinkDirective, LocalDecl, MatchArm, MatchExpr, MatchExprArm, MatchStmt, MemberAccess, MethodDef, NullLiteral, OffsetofExpr, OpaqueDecl, ParallelBlockStmt, Param, PassStmt, PrefixCast, ProcExpr, ProcType, QualifiedName, RangeExpr, ReturnStmt, SizeofExpr, SourceFile, Specialization, StaticAssert, StringLiteral, StructDecl, TupleType, TypeAliasDecl, TypeArgument, TypeParam, TypeParamConstraint, TypeRef, UnaryOp, UnionDecl, UnsafeExpr, UnsafeStmt, ValueTypeParam, VarDecl, VariantArm, VariantDecl, WhenBranch, WhenStmt, WhileStmt

Class Method Summary collapse

Class Method Details

.assign_node_ids(source_file) ⇒ Object



258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
# File 'lib/milk_tea/core/ast.rb', line 258

def self.assign_node_ids(source_file)
  next_id = 0
  node_ids = {}
  path_ids = {}

  visit = ->(node, path = "") do
    return [next_id, path] unless node.is_a?(::Data)

    node_ids[node.object_id] = (next_id += 1)
    current_path = path.empty? ? node.class.name.sub(/\AMilkTea::AST::/, "") : path
    path_ids[current_path] = node_ids[node.object_id]

    if node.respond_to?(:declarations) && node.declarations.is_a?(Array)
      node.declarations.each_with_index { |d, i| visit.call(d, "#{current_path}.declarations[#{i}]") }
    end

    if node.respond_to?(:body)
      visit.call(node.body, "#{current_path}.body")
    end

    node.class.members.each do |field_name|
      next if %i[module_name module_kind].include?(field_name)

      value = node.public_send(field_name)
      next unless value

      field_path = "#{current_path}.#{field_name}"

      case value
      when ::Data
        visit.call(value, field_path)
      when Array
        value.each_with_index do |v, i|
          visit.call(v, "#{field_path}[#{i}]") if v.is_a?(::Data)
        end
      end
    end
  end

  visit.call(source_file)
  source_file.with(node_ids: node_ids.freeze, node_path_ids: path_ids.freeze)
end

.build_chain_from_parts(parts) ⇒ Object



301
302
303
304
305
306
307
308
309
# File 'lib/milk_tea/core/ast.rb', line 301

def self.build_chain_from_parts(parts)
  return nil unless parts.length >= 1

  expr = Identifier.new(name: parts.first)
  parts[1..].each do |part|
    expr = MemberAccess.new(receiver: expr, member: part)
  end
  expr
end